import * as i0 from '@angular/core';
import { input, model, output, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { TranslatePipe } from '@ngx-translate/core';
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
import { ZModalComponent } from '@shival99/z-ui/components/z-modal';
import { zTransform, zMergeClasses, zUuid } from '@shival99/z-ui/utils';
import { NgScrollbar } from 'ngx-scrollbar';
import { cva } from 'class-variance-authority';

const zChatWrapperVariants = cva('z-chat fixed z-[95] pointer-events-none', {
    variants: {
        zPosition: {
            'bottom-right': '',
            'bottom-left': '',
        },
    },
    defaultVariants: {
        zPosition: 'bottom-right',
    },
});
const zChatPanelVariants = cva('absolute bottom-16 flex flex-col overflow-hidden rounded-2xl shadow-2xl transition-all duration-200', {
    variants: {
        zPosition: {
            'bottom-right': 'right-0 origin-bottom-right',
            'bottom-left': 'left-0 origin-bottom-left',
        },
        zSize: {
            sm: 'h-[28rem] w-[20rem]',
            default: 'h-[35rem] w-[25rem]',
            lg: 'h-[39rem] w-[29rem]',
        },
        zOpen: {
            true: 'pointer-events-auto visible translate-y-0 scale-100 opacity-100',
            false: 'pointer-events-none invisible translate-y-3 scale-95 opacity-0',
        },
    },
    defaultVariants: {
        zPosition: 'bottom-right',
        zSize: 'default',
        zOpen: false,
    },
});
const zChatFabVariants = cva('relative inline-flex size-14 items-center justify-center rounded-full shadow-lg ring-1 ring-black/5 transition-all duration-200 hover:scale-[1.03] active:scale-95', {
    variants: {
        zOpen: {
            true: 'bg-background text-foreground border border-border shadow-xl dark:border-white/15 dark:bg-[#2b2b2b] dark:text-white',
            false: 'from-primary via-primary to-primary/75 bg-gradient-to-br text-white shadow-xl',
        },
    },
    defaultVariants: {
        zOpen: false,
    },
});

const DEFAULT_SUGGESTIONS = [
    {
        label: 'i18n_z_ui_chat_ai_suggestion_1',
        prompt: 'Create release notes from recent commits',
        icon: 'lucideSparkles',
    },
    {
        label: 'i18n_z_ui_chat_ai_suggestion_2',
        prompt: 'Suggest test cases for a new feature',
        icon: 'lucideFlaskConical',
    },
    { label: 'i18n_z_ui_chat_ai_suggestion_3', prompt: 'Generate a concise PR summary', icon: 'lucideGitPullRequest' },
];
class ZChatComponent {
    class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
    zOpen = model(false, ...(ngDevMode ? [{ debugName: "zOpen" }] : []));
    zMessages = model([], ...(ngDevMode ? [{ debugName: "zMessages" }] : []));
    zTitle = input('i18n_z_ui_chat_ai_title', ...(ngDevMode ? [{ debugName: "zTitle" }] : []));
    zSubtitle = input('i18n_z_ui_chat_ai_subtitle', ...(ngDevMode ? [{ debugName: "zSubtitle" }] : []));
    zPlaceholder = input('i18n_z_ui_chat_ai_placeholder', ...(ngDevMode ? [{ debugName: "zPlaceholder" }] : []));
    zPosition = input('bottom-right', ...(ngDevMode ? [{ debugName: "zPosition" }] : []));
    zOffset = input({}, ...(ngDevMode ? [{ debugName: "zOffset" }] : []));
    zSize = input('default', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
    zSuggestions = input(DEFAULT_SUGGESTIONS, ...(ngDevMode ? [{ debugName: "zSuggestions" }] : []));
    zShowSuggestions = input(true, { ...(ngDevMode ? { debugName: "zShowSuggestions" } : {}), transform: zTransform });
    zShowPulse = input(true, { ...(ngDevMode ? { debugName: "zShowPulse" } : {}), transform: zTransform });
    zDisabled = input(false, { ...(ngDevMode ? { debugName: "zDisabled" } : {}), transform: zTransform });
    zLoading = input(false, { ...(ngDevMode ? { debugName: "zLoading" } : {}), transform: zTransform });
    zAllowAttachments = input(true, { ...(ngDevMode ? { debugName: "zAllowAttachments" } : {}), transform: zTransform });
    zAcceptedFiles = input('image/*,.pdf,.doc,.docx,.txt,.csv,.xlsx', ...(ngDevMode ? [{ debugName: "zAcceptedFiles" }] : []));
    zAutoReply = input(true, { ...(ngDevMode ? { debugName: "zAutoReply" } : {}), transform: zTransform });
    zAutoReplyDelay = input(1200, ...(ngDevMode ? [{ debugName: "zAutoReplyDelay" }] : []));
    zFabIcon = input('lucideMessageSquareDot', ...(ngDevMode ? [{ debugName: "zFabIcon" }] : []));
    zBotIcon = input('lucideBot', ...(ngDevMode ? [{ debugName: "zBotIcon" }] : []));
    zSendIcon = input('lucideArrowUp', ...(ngDevMode ? [{ debugName: "zSendIcon" }] : []));
    zSend = output();
    zResponse = output();
    zToggle = output();
    zClear = output();
    draftMessage = signal('', ...(ngDevMode ? [{ debugName: "draftMessage" }] : []));
    showRipple = signal(false, ...(ngDevMode ? [{ debugName: "showRipple" }] : []));
    attachments = signal([], ...(ngDevMode ? [{ debugName: "attachments" }] : []));
    isComposerExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isComposerExpanded" }] : []));
    isComposerOverflowing = signal(false, ...(ngDevMode ? [{ debugName: "isComposerOverflowing" }] : []));
    isPreviewVisible = signal(false, ...(ngDevMode ? [{ debugName: "isPreviewVisible" }] : []));
    previewImage = signal(null, ...(ngDevMode ? [{ debugName: "previewImage" }] : []));
    _mockTyping = signal(false, ...(ngDevMode ? [{ debugName: "_mockTyping" }] : []));
    _messagesScrollbarRef = viewChild('messagesScrollbar', ...(ngDevMode ? [{ debugName: "_messagesScrollbarRef" }] : []));
    _chatInputRef = viewChild('chatInput', ...(ngDevMode ? [{ debugName: "_chatInputRef" }] : []));
    _fileInputRef = viewChild('fileInput', ...(ngDevMode ? [{ debugName: "_fileInputRef" }] : []));
    _mockReplyTimer = null;
    _rippleTimer = null;
    _scrollTimer = null;
    wrapperClasses = computed(() => zMergeClasses(zChatWrapperVariants({ zPosition: this.zPosition() }), this.class()), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : []));
    wrapperTop = computed(() => this._resolveOffsetValue('top'), ...(ngDevMode ? [{ debugName: "wrapperTop" }] : []));
    wrapperRight = computed(() => this._resolveOffsetValue('right'), ...(ngDevMode ? [{ debugName: "wrapperRight" }] : []));
    wrapperBottom = computed(() => this._resolveOffsetValue('bottom'), ...(ngDevMode ? [{ debugName: "wrapperBottom" }] : []));
    wrapperLeft = computed(() => this._resolveOffsetValue('left'), ...(ngDevMode ? [{ debugName: "wrapperLeft" }] : []));
    panelClasses = computed(() => zChatPanelVariants({
        zPosition: this.zPosition(),
        zSize: this.zSize(),
        zOpen: this.zOpen(),
    }), ...(ngDevMode ? [{ debugName: "panelClasses" }] : []));
    fabClasses = computed(() => zChatFabVariants({
        zOpen: this.zOpen(),
    }), ...(ngDevMode ? [{ debugName: "fabClasses" }] : []));
    isTyping = computed(() => this.zLoading() || this._mockTyping(), ...(ngDevMode ? [{ debugName: "isTyping" }] : []));
    canSend = computed(() => (!!this.draftMessage().trim() || this.attachments().length > 0) && !this.zDisabled() && !this.isTyping(), ...(ngDevMode ? [{ debugName: "canSend" }] : []));
    hasMessages = computed(() => this.zMessages().length > 0, ...(ngDevMode ? [{ debugName: "hasMessages" }] : []));
    showEmptyState = computed(() => !this.hasMessages() && this.zShowSuggestions(), ...(ngDevMode ? [{ debugName: "showEmptyState" }] : []));
    previewImageSizeLabel = computed(() => {
        const preview = this.previewImage();
        return preview ? this.formatFileSize(preview.size) : '';
    }, ...(ngDevMode ? [{ debugName: "previewImageSizeLabel" }] : []));
    ngOnDestroy() {
        if (this._mockReplyTimer) {
            clearTimeout(this._mockReplyTimer);
        }
        if (this._rippleTimer) {
            clearTimeout(this._rippleTimer);
        }
        if (this._scrollTimer) {
            clearTimeout(this._scrollTimer);
        }
        const filesInMessages = this.zMessages().flatMap(item => item.files ?? []);
        this._releaseAttachmentUrls(filesInMessages);
        this._releaseAttachmentUrls(this.attachments());
    }
    open() {
        if (this.zOpen()) {
            return;
        }
        this._toggle(true);
    }
    close() {
        if (!this.zOpen()) {
            return;
        }
        this._toggle(false);
    }
    clearMessages() {
        const filesInMessages = this.zMessages().flatMap(item => item.files ?? []);
        this._releaseAttachmentUrls(filesInMessages);
        this.zMessages.set([]);
        this.zClear.emit();
    }
    onToggle() {
        this._toggle(!this.zOpen());
    }
    onSuggestionSelect(item) {
        this.draftMessage.set((item.prompt ?? item.label).trim());
        this.onSendMessage();
    }
    onClickAttach() {
        this._fileInputRef()?.nativeElement.click();
    }
    onFileChange(event) {
        const inputEl = event.target;
        const { files } = inputEl;
        if (!files || files.length === 0) {
            return;
        }
        this._appendFiles(Array.from(files));
        inputEl.value = '';
    }
    onTextareaPaste(event) {
        if (!this.zAllowAttachments()) {
            return;
        }
        const items = event.clipboardData?.items;
        if (!items || items.length === 0) {
            return;
        }
        const files = [];
        Array.from(items).forEach(item => {
            if (item.kind === 'file') {
                const file = item.getAsFile();
                if (file) {
                    files.push(file);
                }
            }
        });
        if (files.length > 0) {
            event.preventDefault();
            this._appendFiles(files);
        }
    }
    removeAttachment(id) {
        const target = this.attachments().find(item => item.id === id);
        if (target?.previewUrl) {
            URL.revokeObjectURL(target.previewUrl);
        }
        this.attachments.update(files => files.filter(item => item.id !== id));
    }
    formatFileSize(size) {
        if (size < 1024) {
            return `${size} B`;
        }
        if (size < 1024 * 1024) {
            return `${(size / 1024).toFixed(1)} KB`;
        }
        if (size < 1024 * 1024 * 1024) {
            return `${(size / (1024 * 1024)).toFixed(1)} MB`;
        }
        return `${(size / (1024 * 1024 * 1024)).toFixed(1)} GB`;
    }
    isImageAttachment(file) {
        return file.type.startsWith('image/');
    }
    openImagePreview(file) {
        if (!file.previewUrl || !this.isImageAttachment(file)) {
            return;
        }
        this.previewImage.set({
            url: file.previewUrl,
            name: file.name,
            size: file.size,
        });
        this.isPreviewVisible.set(true);
    }
    closeImagePreview() {
        setTimeout(() => {
            this.isPreviewVisible.set(false);
            this.previewImage.set(null);
        }, 300);
    }
    onInputKeydown(event) {
        if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault();
            this.onSendMessage();
        }
    }
    onTextareaInput(event) {
        const textarea = event.target;
        textarea.style.height = 'auto';
        const nextHeight = Math.min(textarea.scrollHeight, 66);
        textarea.style.height = `${nextHeight}px`;
        textarea.style.overflowY = textarea.scrollHeight > 66 ? 'auto' : 'hidden';
        this.isComposerExpanded.set(nextHeight > 44 || textarea.value.includes('\n'));
        this.isComposerOverflowing.set(textarea.scrollHeight > nextHeight + 1);
    }
    onSendMessage() {
        const message = this.draftMessage().trim();
        if (!message && this.attachments().length === 0) {
            return;
        }
        if (!this.canSend()) {
            return;
        }
        const attachedFiles = this.attachments().map(file => ({
            ...file,
            // Keep message preview URLs alive after composer files are cleared.
            previewUrl: this._createMessagePreviewUrl(file),
            file: undefined,
        }));
        const messageContent = message || `Attached ${attachedFiles.length} file(s).`;
        const userMessage = this._createMessage('user', messageContent, attachedFiles);
        const nextMessages = [...this.zMessages(), userMessage];
        this.zMessages.set(nextMessages);
        this._ensureBottomVisible();
        this.draftMessage.set('');
        this._releaseAttachmentUrls(this.attachments());
        this.attachments.set([]);
        const inputEl = this._chatInputRef()?.nativeElement;
        if (inputEl) {
            inputEl.style.height = '66px';
            inputEl.style.overflowY = 'hidden';
        }
        this.isComposerExpanded.set(false);
        this.isComposerOverflowing.set(false);
        this.zSend.emit({ message: messageContent, files: attachedFiles, messages: nextMessages });
        if (this.zAutoReply()) {
            this._simulateReply(messageContent, attachedFiles.length);
        }
        this._focusInputSoon();
    }
    _toggle(isOpen) {
        this.zOpen.set(isOpen);
        this.zToggle.emit(isOpen);
        this._triggerRipple();
        if (isOpen) {
            this._focusInputSoon();
            requestAnimationFrame(() => {
                this._scheduleScrollToBottom(250);
            });
        }
    }
    _createMessage(role, content, files) {
        return {
            id: zUuid(),
            role,
            content,
            files,
            createdAt: Date.now(),
        };
    }
    _simulateReply(userMessage, fileCount) {
        if (this._mockReplyTimer) {
            clearTimeout(this._mockReplyTimer);
        }
        this._mockTyping.set(true);
        const delay = Math.max(200, this.zAutoReplyDelay());
        this._mockReplyTimer = setTimeout(() => {
            this._mockTyping.set(false);
            const botMessage = this._createMessage('assistant', this._buildMockReply(userMessage, fileCount));
            this.zMessages.update(messages => [...messages, botMessage]);
            this.zResponse.emit(botMessage);
            this._ensureBottomVisible();
        }, delay);
    }
    _buildMockReply(message, fileCount) {
        const normalized = message.toLowerCase();
        if (fileCount > 0) {
            return `Received ${fileCount} attachment(s). I can summarize, extract key points, or draft a reply from these files.`;
        }
        if (normalized.includes('deploy') || normalized.includes('release')) {
            return 'Deployment checklist: run lint, build artifact, smoke test staging, then promote to production.';
        }
        if (normalized.includes('bug') || normalized.includes('error')) {
            return 'Please share logs, repro steps, expected behavior, and current environment so I can triage precisely.';
        }
        if (normalized.includes('test')) {
            return 'I suggest coverage for happy path, validation failures, edge cases, and retry/error handling.';
        }
        return 'Got it. I can help you break this task into actionable steps and propose code changes.';
    }
    _triggerRipple() {
        this.showRipple.set(true);
        if (this._rippleTimer) {
            clearTimeout(this._rippleTimer);
        }
        this._rippleTimer = setTimeout(() => this.showRipple.set(false), 350);
    }
    onMessagesScrollbarInit() {
        this._ensureBottomVisible();
    }
    onEscapeKey() {
        if (this.previewImage()) {
            this.closeImagePreview();
        }
    }
    _scheduleScrollToBottom(delay = 0, duration = 300) {
        if (this._scrollTimer) {
            clearTimeout(this._scrollTimer);
        }
        this._scrollTimer = setTimeout(() => {
            this._scrollToBottom(duration);
        }, delay);
    }
    _ensureBottomVisible() {
        this._scrollToBottom(0);
        requestAnimationFrame(() => {
            this._scrollToBottom(0);
            this._scheduleScrollToBottom(90, 0);
        });
    }
    _scrollToBottom(duration = 300) {
        const scrollbar = this._messagesScrollbarRef();
        if (!scrollbar) {
            return;
        }
        void scrollbar.scrollTo({
            bottom: 0,
            duration,
            easing: { x1: 0.25, y1: 0.1, x2: 0.25, y2: 1 },
        });
    }
    _focusInputSoon() {
        setTimeout(() => this._chatInputRef()?.nativeElement.focus(), 50);
    }
    _releaseAttachmentUrls(files) {
        files.forEach(file => {
            if (file.previewUrl) {
                URL.revokeObjectURL(file.previewUrl);
            }
        });
    }
    _appendFiles(files) {
        const nextFiles = files.map(file => ({
            id: zUuid(),
            name: file.name,
            size: file.size,
            type: file.type,
            previewUrl: file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined,
            file,
        }));
        this.attachments.update(current => [...current, ...nextFiles]);
    }
    _createMessagePreviewUrl(file) {
        if (!this.isImageAttachment(file)) {
            return undefined;
        }
        if (file.file) {
            return URL.createObjectURL(file.file);
        }
        return file.previewUrl;
    }
    _resolveOffsetValue(side) {
        const override = this.zOffset()[side];
        if (override !== undefined && override !== null && override !== '') {
            return typeof override === 'number' ? `${override}px` : String(override);
        }
        const defaults = this.zPosition() === 'bottom-left'
            ? { top: null, right: null, bottom: '1.25rem', left: '1.5rem' }
            : { top: null, right: '1.5rem', bottom: '1.25rem', left: null };
        return defaults[side];
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZChatComponent, isStandalone: true, selector: "z-chat", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zOpen: { classPropertyName: "zOpen", publicName: "zOpen", isSignal: true, isRequired: false, transformFunction: null }, zMessages: { classPropertyName: "zMessages", publicName: "zMessages", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zSubtitle: { classPropertyName: "zSubtitle", publicName: "zSubtitle", isSignal: true, isRequired: false, transformFunction: null }, zPlaceholder: { classPropertyName: "zPlaceholder", publicName: "zPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zOffset: { classPropertyName: "zOffset", publicName: "zOffset", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zSuggestions: { classPropertyName: "zSuggestions", publicName: "zSuggestions", isSignal: true, isRequired: false, transformFunction: null }, zShowSuggestions: { classPropertyName: "zShowSuggestions", publicName: "zShowSuggestions", isSignal: true, isRequired: false, transformFunction: null }, zShowPulse: { classPropertyName: "zShowPulse", publicName: "zShowPulse", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zLoading: { classPropertyName: "zLoading", publicName: "zLoading", isSignal: true, isRequired: false, transformFunction: null }, zAllowAttachments: { classPropertyName: "zAllowAttachments", publicName: "zAllowAttachments", isSignal: true, isRequired: false, transformFunction: null }, zAcceptedFiles: { classPropertyName: "zAcceptedFiles", publicName: "zAcceptedFiles", isSignal: true, isRequired: false, transformFunction: null }, zAutoReply: { classPropertyName: "zAutoReply", publicName: "zAutoReply", isSignal: true, isRequired: false, transformFunction: null }, zAutoReplyDelay: { classPropertyName: "zAutoReplyDelay", publicName: "zAutoReplyDelay", isSignal: true, isRequired: false, transformFunction: null }, zFabIcon: { classPropertyName: "zFabIcon", publicName: "zFabIcon", isSignal: true, isRequired: false, transformFunction: null }, zBotIcon: { classPropertyName: "zBotIcon", publicName: "zBotIcon", isSignal: true, isRequired: false, transformFunction: null }, zSendIcon: { classPropertyName: "zSendIcon", publicName: "zSendIcon", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOpen: "zOpenChange", zMessages: "zMessagesChange", zSend: "zSend", zResponse: "zResponse", zToggle: "zToggle", zClear: "zClear" }, host: { listeners: { "document:keydown.escape": "onEscapeKey()" }, classAttribute: "z-chat block" }, viewQueries: [{ propertyName: "_messagesScrollbarRef", first: true, predicate: ["messagesScrollbar"], descendants: true, isSignal: true }, { propertyName: "_chatInputRef", first: true, predicate: ["chatInput"], descendants: true, isSignal: true }, { propertyName: "_fileInputRef", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], exportAs: ["zChat"], ngImport: i0, template: "<div\n  [class]=\"wrapperClasses()\"\n  [style.top]=\"wrapperTop()\"\n  [style.right]=\"wrapperRight()\"\n  [style.bottom]=\"wrapperBottom()\"\n  [style.left]=\"wrapperLeft()\">\n  <div class=\"relative\">\n    <section class=\"z-chat-panel-shell\" [class]=\"panelClasses()\">\n      <header class=\"from-primary/95 to-primary/75 text-primary-foreground bg-gradient-to-r px-4 py-3.5\">\n        <div class=\"flex items-start justify-between gap-3\">\n          <div class=\"min-w-0\">\n            <div class=\"flex items-center gap-2\">\n              <span\n                class=\"bg-primary-foreground/15 relative inline-flex size-8 shrink-0 items-center justify-center rounded-full\">\n                <z-icon [zType]=\"zBotIcon()\" zSize=\"16\" class=\"text-primary-foreground\" />\n                <span\n                  class=\"ring-primary inline-block size-2.5 rounded-full bg-emerald-300 ring-2\"\n                  style=\"position: absolute; right: -0.0625rem; bottom: -0.0625rem\"></span>\n              </span>\n              <h3 class=\"truncate text-sm font-semibold\">{{ zTitle() | translate }}</h3>\n            </div>\n          </div>\n          <div class=\"flex items-center gap-1\">\n            <button\n              type=\"button\"\n              class=\"text-primary-foreground/90 hover:bg-primary-foreground/15 inline-flex size-8 cursor-pointer items-center justify-center rounded-md transition\"\n              (click)=\"clearMessages()\"\n              title=\"{{ 'i18n_z_ui_chat_ai_new_chat' | translate }}\">\n              <z-icon zType=\"lucideRefreshCcw\" zSize=\"17\" />\n            </button>\n            <button\n              type=\"button\"\n              class=\"text-primary-foreground/90 hover:bg-primary-foreground/15 inline-flex size-8 cursor-pointer items-center justify-center rounded-md transition\"\n              (click)=\"close()\"\n              title=\"{{ 'i18n_z_ui_chat_ai_close' | translate }}\">\n              <z-icon zType=\"lucideChevronDown\" zSize=\"18\" />\n            </button>\n          </div>\n        </div>\n      </header>\n\n      <div class=\"z-chat-lower-shell\">\n        <ng-scrollbar\n          #messagesScrollbar\n          (afterInit)=\"onMessagesScrollbarInit()\"\n          class=\"z-chat-scrollbar z-chat-content-surface flex-1 overflow-x-hidden\"\n          track=\"vertical\"\n          orientation=\"vertical\"\n          appearance=\"compact\"\n          visibility=\"hover\">\n          <div class=\"z-chat-messages\">\n            @if (hasMessages()) {\n              @for (item of zMessages(); track item.id) {\n                <div\n                  class=\"z-chat-message z-chat-message--enter\"\n                  [class.justify-end]=\"item.role === 'user'\"\n                  [class.justify-start]=\"item.role === 'assistant'\">\n                  <div\n                    class=\"z-chat-message-bubble max-w-[88%] min-w-0 rounded-2xl px-3 py-2.5 text-sm leading-5 [overflow-wrap:anywhere] break-all shadow-xs\"\n                    [class.bg-primary]=\"item.role === 'user'\"\n                    [class.text-primary-foreground]=\"item.role === 'user'\"\n                    [class.rounded-br-md]=\"item.role === 'user'\"\n                    [class.bg-background]=\"item.role === 'assistant'\"\n                    [class.border-border/60]=\"item.role === 'assistant'\"\n                    [class.text-foreground]=\"item.role === 'assistant'\"\n                    [class.rounded-bl-md]=\"item.role === 'assistant'\"\n                    [class.border]=\"item.role === 'assistant'\">\n                    @if (item.files && item.files.length > 0) {\n                      <div class=\"mb-2 flex flex-col gap-1.5\">\n                        @for (file of item.files; track file.id) {\n                          <div\n                            class=\"flex items-center gap-2 rounded-[0.5rem] px-2 py-1.5 text-xs\"\n                            [class.bg-white/15]=\"item.role === 'user'\"\n                            [class.bg-muted/40]=\"item.role === 'assistant'\">\n                            @if (isImageAttachment(file) && file.previewUrl) {\n                              <img\n                                [src]=\"file.previewUrl\"\n                                [alt]=\"file.name\"\n                                class=\"size-8 cursor-pointer rounded-[0.5rem] object-cover\"\n                                (click)=\"openImagePreview(file)\"\n                                title=\"Click to preview\" />\n                            } @else {\n                              <span\n                                class=\"bg-background/80 text-muted-foreground inline-flex size-8 items-center justify-center rounded-[0.5rem]\"\n                                [class.bg-white/20]=\"item.role === 'user'\"\n                                [class.text-white]=\"item.role === 'user'\">\n                                <z-icon zType=\"lucideFileText\" zSize=\"14\" />\n                              </span>\n                            }\n                            <div class=\"min-w-0 flex-1\">\n                              <p class=\"truncate text-[0.6875rem] font-medium\">{{ file.name }}</p>\n                              <p class=\"truncate text-[0.625rem] opacity-80\">{{ formatFileSize(file.size) }}</p>\n                            </div>\n                          </div>\n                        }\n                      </div>\n                    }\n                    {{ item.content }}\n                  </div>\n                </div>\n              }\n            } @else if (showEmptyState()) {\n              <div class=\"flex h-full min-h-60 flex-col items-center justify-center px-2 text-center\">\n                <div\n                  class=\"from-primary/20 to-primary/5 mb-3 inline-flex size-14 items-center justify-center rounded-full bg-gradient-to-br\">\n                  <z-icon zType=\"lucideBot\" zSize=\"28\" class=\"text-primary\" />\n                </div>\n                <h4 class=\"text-foreground text-sm font-semibold\">{{ 'i18n_z_ui_chat_ai_empty_title' | translate }}</h4>\n                <p class=\"text-muted-foreground mt-1 text-xs\">{{ 'i18n_z_ui_chat_ai_empty_desc' | translate }}</p>\n\n                @if (zSuggestions().length > 0) {\n                  <div class=\"mt-4 flex w-full flex-col gap-2\">\n                    @for (item of zSuggestions(); track item.label) {\n                      <button\n                        type=\"button\"\n                        class=\"z-chat-suggestion-item bg-background/95 hover:bg-background border-border/60 text-foreground flex w-full cursor-pointer items-center gap-2 rounded-xl border px-3 py-2 text-left text-xs transition hover:shadow-sm\"\n                        [style.animation-delay.ms]=\"$index * 70\"\n                        (click)=\"onSuggestionSelect(item)\">\n                        @if (item.icon) {\n                          <z-icon [zType]=\"item.icon!\" zSize=\"14\" class=\"text-primary shrink-0\" />\n                        }\n                        <span class=\"line-clamp-2\">{{ item.label | translate }}</span>\n                      </button>\n                    }\n                  </div>\n                }\n              </div>\n            }\n\n            @if (isTyping()) {\n              <div class=\"z-chat-message z-chat-message--enter justify-start\">\n                <div class=\"bg-background border-border/60 rounded-2xl rounded-bl-md border px-3 py-2\">\n                  <div class=\"flex items-center gap-1\">\n                    <span class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"></span>\n                    <span\n                      class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"\n                      style=\"animation-delay: 0.15s\"></span>\n                    <span\n                      class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"\n                      style=\"animation-delay: 0.3s\"></span>\n                  </div>\n                </div>\n              </div>\n            }\n          </div>\n        </ng-scrollbar>\n\n        <footer class=\"z-chat-footer-surface p-3\">\n          @if (attachments().length > 0) {\n            <div class=\"mb-2 flex max-h-32 flex-col gap-2 overflow-y-auto pr-1\">\n              @for (file of attachments(); track file.id) {\n                <div\n                  class=\"bg-muted/45 border-border/55 relative flex w-full items-center gap-2 rounded-[0.5rem] border px-2 py-1.5\">\n                  @if (isImageAttachment(file) && file.previewUrl) {\n                    <img\n                      [src]=\"file.previewUrl\"\n                      [alt]=\"file.name\"\n                      class=\"size-8 shrink-0 cursor-pointer rounded-[0.5rem] object-cover\"\n                      (click)=\"openImagePreview(file)\"\n                      title=\"Click to preview\" />\n                  } @else {\n                    <span\n                      class=\"bg-background text-muted-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-[0.5rem]\">\n                      <z-icon zType=\"lucideFileText\" zSize=\"14\" />\n                    </span>\n                  }\n                  <div class=\"min-w-0 flex-1\">\n                    <p class=\"truncate text-[0.6875rem] font-medium\">{{ file.name }}</p>\n                    <p class=\"text-muted-foreground truncate text-[0.625rem]\">{{ formatFileSize(file.size) }}</p>\n                  </div>\n                  <button\n                    type=\"button\"\n                    class=\"bg-background/80 hover:bg-background text-muted-foreground inline-flex size-5 cursor-pointer items-center justify-center rounded-full transition\"\n                    (click)=\"removeAttachment(file.id)\">\n                    <z-icon zType=\"lucideX\" zSize=\"12\" />\n                  </button>\n                </div>\n              }\n            </div>\n          }\n\n          <div class=\"z-chat-composer-shell\">\n            <div class=\"z-chat-composer-main\" [class.z-chat-composer__field--overflow]=\"isComposerOverflowing()\">\n              <textarea\n                #chatInput\n                class=\"z-chat-composer-textarea\"\n                [placeholder]=\"zPlaceholder() | translate\"\n                [disabled]=\"zDisabled()\"\n                [ngModel]=\"draftMessage()\"\n                (ngModelChange)=\"draftMessage.set($event)\"\n                (input)=\"onTextareaInput($event)\"\n                (paste)=\"onTextareaPaste($event)\"\n                (keydown)=\"onInputKeydown($event)\"\n                rows=\"3\"></textarea>\n            </div>\n\n            <div class=\"z-chat-composer-toolbar\">\n              <div class=\"z-chat-composer-toolbar-left\">\n                @if (zAllowAttachments()) {\n                  <input\n                    #fileInput\n                    type=\"file\"\n                    class=\"hidden\"\n                    [attr.accept]=\"zAcceptedFiles()\"\n                    multiple\n                    (change)=\"onFileChange($event)\" />\n                  <button\n                    type=\"button\"\n                    class=\"z-chat-composer-tool-btn\"\n                    [disabled]=\"zDisabled()\"\n                    (click)=\"onClickAttach()\"\n                    title=\"{{ 'i18n_z_ui_chat_ai_attach' | translate }}\">\n                    <z-icon zType=\"lucidePlus\" zSize=\"18\" />\n                  </button>\n                }\n              </div>\n\n              <div class=\"z-chat-composer-toolbar-right\">\n                <button\n                  type=\"button\"\n                  class=\"z-chat-composer-send-btn\"\n                  [disabled]=\"!canSend()\"\n                  (click)=\"onSendMessage()\"\n                  title=\"{{ 'i18n_z_ui_chat_ai_send' | translate }}\">\n                  <z-icon\n                    [zType]=\"isTyping() ? 'lucideLoaderCircle' : zSendIcon()\"\n                    zSize=\"16\"\n                    [class]=\"isTyping() ? 'animate-spin' : ''\" />\n                </button>\n              </div>\n            </div>\n          </div>\n        </footer>\n      </div>\n\n      <z-modal\n        [zVisible]=\"isPreviewVisible()\"\n        [zTitle]=\"previewImage()?.name\"\n        [zDescription]=\"previewImageSizeLabel()\"\n        zWidth=\"min(92vw, 720px)\"\n        [zHideFooter]=\"true\"\n        [zMaskClosable]=\"true\"\n        zOverlay=\"blur\"\n        (zCancel)=\"closeImagePreview()\">\n        <div class=\"z-chat-preview-modal-body\">\n          <img [src]=\"previewImage()?.url\" [alt]=\"previewImage()?.name\" class=\"z-chat-preview-image\" />\n        </div>\n      </z-modal>\n    </section>\n\n    <button\n      type=\"button\"\n      class=\"pointer-events-auto cursor-pointer\"\n      [class]=\"fabClasses()\"\n      (click)=\"onToggle()\"\n      [attr.aria-expanded]=\"zOpen()\"\n      [attr.aria-label]=\"'i18n_z_ui_chat_ai_toggle' | translate\"\n      title=\"{{ 'i18n_z_ui_chat_ai_toggle' | translate }}\">\n      @if (zShowPulse() && !zOpen()) {\n        <span class=\"bg-primary/30 absolute inset-0 animate-ping rounded-full\"></span>\n      }\n\n      @if (showRipple()) {\n        <span class=\"bg-primary-foreground/30 absolute inset-0 animate-ping rounded-full\"></span>\n      }\n\n      <z-icon\n        [zType]=\"zOpen() ? 'lucideX' : zFabIcon()\"\n        zSize=\"24\"\n        class=\"relative z-1 transition-transform duration-200\"\n        [class.rotate-180]=\"zOpen()\" />\n    </button>\n  </div>\n</div>\n", styles: [".z-chat textarea{scrollbar-width:thin}.z-chat-panel-shell{box-shadow:0 0 28px #00000024!important}:is(.dark,[data-theme=dark]) .z-chat-panel-shell{box-shadow:0 0 28px #00000057!important}.z-chat-composer__field--overflow:after{position:absolute;right:0;bottom:0;left:0;height:1rem;pointer-events:none;content:\"\";background:linear-gradient(to top,var(--background) 22%,transparent)}.z-chat-composer-shell{position:relative;display:flex;width:100%;flex-direction:column;border:1px solid color-mix(in oklab,var(--border) 82%,transparent);border-radius:1rem;background:linear-gradient(180deg,color-mix(in oklab,var(--card) 98%,var(--background) 2%),color-mix(in oklab,var(--card) 92%,var(--background) 8%));box-shadow:0 6px 18px #00000014;transition:box-shadow .2s ease}.z-chat-composer-shell:focus-within{box-shadow:0 6px 18px #00000014}:is(.dark,[data-theme=dark]) .z-chat-composer-shell{border-color:var(--border);background:linear-gradient(180deg,color-mix(in oklab,var(--card) 96%,var(--background) 4%),color-mix(in oklab,var(--card) 88%,var(--background) 12%));box-shadow:0 10px 24px #00000057}.z-chat-composer-main{position:relative;overflow:hidden;padding:.7rem .35rem .45rem .85rem}.z-chat-composer-textarea{width:100%;height:4.125rem;max-height:4.125rem;border:none;background:transparent;resize:none;overflow-x:hidden;font-size:.875rem;line-height:1.4rem;color:var(--foreground);outline:none;padding-right:.2rem;scrollbar-width:thin;overflow-wrap:anywhere;word-break:break-word}.z-chat-composer-textarea::placeholder{color:var(--muted-foreground)}.z-chat-composer-textarea::-webkit-scrollbar{width:.375rem}.z-chat-composer-textarea::-webkit-scrollbar-track{background:transparent}.z-chat-composer-textarea::-webkit-scrollbar-thumb{border-radius:62.4375rem;background:#64748b73}:is(.dark,[data-theme=dark]) .z-chat-composer-textarea::-webkit-scrollbar-thumb{background:#94a3b88c}.z-chat-composer-toolbar{display:flex;align-items:center;justify-content:space-between;border-top:.0625rem solid rgba(219,219,219,.6);padding:.55rem .7rem .65rem}:is(.dark,[data-theme=dark]) .z-chat-composer-toolbar{border-top-color:#00000038}.z-chat-composer-toolbar-left,.z-chat-composer-toolbar-right{display:flex;align-items:center}.z-chat-composer-tool-btn{display:inline-flex;height:1.75rem;width:1.75rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.6rem;border:none;background:transparent;color:#374151;transition:background-color .2s ease}.z-chat-composer-tool-btn:hover{background:#0000000f}:is(.dark,[data-theme=dark]) .z-chat-composer-tool-btn{color:#e5e7ebe6}:is(.dark,[data-theme=dark]) .z-chat-composer-tool-btn:hover{background:#ffffff1a}.z-chat-composer-tool-btn:disabled{cursor:not-allowed;opacity:.5}.z-chat-composer-send-btn{display:inline-flex;height:2rem;width:2rem;cursor:pointer;align-items:center;justify-content:center;border-radius:62.4375rem;border:1px solid rgba(0,0,0,.1);background:var(--primary);color:var(--primary-foreground);box-shadow:0 2px 8px #0000002e,inset 0 1px #ffffff2e;transition:transform .15s ease,opacity .2s ease,box-shadow .2s ease}.z-chat-composer-send-btn:hover{transform:translateY(-.0625rem);box-shadow:0 4px 12px #00000038,inset 0 1px #ffffff38}.z-chat-composer-send-btn:disabled{cursor:not-allowed;opacity:.45;box-shadow:none}.z-chat-scrollbar{contain:layout}.z-chat-content-surface{background:var(--card)}.z-chat-lower-shell{display:flex;min-height:0;flex:1;flex-direction:column;overflow:hidden;background:var(--card);color:var(--card-foreground);border:1px solid transparent;border-top:0;border-bottom-right-radius:1rem;border-bottom-left-radius:1rem}:is(.dark,[data-theme=dark]) .z-chat-lower-shell{border-color:var(--border);border-top:0}.z-chat-footer-surface{background:transparent;border-top:.0625rem solid color-mix(in oklab,var(--border) 70%,transparent)}:is(.dark,[data-theme=dark]) .z-chat-footer-surface{background:transparent;border-top-color:var(--border)}.z-chat-messages{min-height:100%;overflow-x:hidden;padding:.875rem .75rem;contain:content}.z-chat-message{display:flex;margin:.5rem 0;padding:0 2px;transform-origin:bottom center;contain:layout style}.z-chat-message-bubble{transform:translateZ(0);backface-visibility:hidden}.z-chat-message--enter{animation:z-chat-message-push-in .3s ease-out;will-change:transform,opacity}.z-chat-suggestion-item{animation:z-chat-suggestion-reveal .28s ease-out both;will-change:transform,opacity}.z-chat-preview-modal-body{display:flex;align-items:center;justify-content:center;max-height:min(70vh,40rem);padding:.25rem}.z-chat-preview-image{max-width:100%;max-height:min(66vh,37.5rem);border-radius:.5rem;object-fit:contain}@keyframes z-chat-message-push-in{0%{opacity:0;transform:translateY(.9375rem) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes z-chat-suggestion-reveal{0%{opacity:0;transform:translateY(.5rem) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZModalComponent, selector: "z-modal", inputs: ["class", "zBodyClass", "zVisible", "zTitle", "zDescription", "zWidth", "zClosable", "zMaskClosable", "zHideHeader", "zHideFooter", "zOkText", "zCancelText", "zOkDestructive", "zOkDisabled", "zLoading", "zContentLoading", "zSkeletonRows", "zOverlay"], outputs: ["zOk", "zCancel", "zAfterClose", "zScrollbar", "zVisibleChange"], exportAs: ["zModal"] }, { kind: "component", type: NgScrollbar, selector: "ng-scrollbar:not([externalViewport]), [ngScrollbar]", exportAs: ["ngScrollbar"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZChatComponent, decorators: [{
            type: Component,
            args: [{ selector: 'z-chat', imports: [FormsModule, TranslatePipe, ZIconComponent, ZModalComponent, NgScrollbar], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
                        class: 'z-chat block',
                        '(document:keydown.escape)': 'onEscapeKey()',
                    }, exportAs: 'zChat', template: "<div\n  [class]=\"wrapperClasses()\"\n  [style.top]=\"wrapperTop()\"\n  [style.right]=\"wrapperRight()\"\n  [style.bottom]=\"wrapperBottom()\"\n  [style.left]=\"wrapperLeft()\">\n  <div class=\"relative\">\n    <section class=\"z-chat-panel-shell\" [class]=\"panelClasses()\">\n      <header class=\"from-primary/95 to-primary/75 text-primary-foreground bg-gradient-to-r px-4 py-3.5\">\n        <div class=\"flex items-start justify-between gap-3\">\n          <div class=\"min-w-0\">\n            <div class=\"flex items-center gap-2\">\n              <span\n                class=\"bg-primary-foreground/15 relative inline-flex size-8 shrink-0 items-center justify-center rounded-full\">\n                <z-icon [zType]=\"zBotIcon()\" zSize=\"16\" class=\"text-primary-foreground\" />\n                <span\n                  class=\"ring-primary inline-block size-2.5 rounded-full bg-emerald-300 ring-2\"\n                  style=\"position: absolute; right: -0.0625rem; bottom: -0.0625rem\"></span>\n              </span>\n              <h3 class=\"truncate text-sm font-semibold\">{{ zTitle() | translate }}</h3>\n            </div>\n          </div>\n          <div class=\"flex items-center gap-1\">\n            <button\n              type=\"button\"\n              class=\"text-primary-foreground/90 hover:bg-primary-foreground/15 inline-flex size-8 cursor-pointer items-center justify-center rounded-md transition\"\n              (click)=\"clearMessages()\"\n              title=\"{{ 'i18n_z_ui_chat_ai_new_chat' | translate }}\">\n              <z-icon zType=\"lucideRefreshCcw\" zSize=\"17\" />\n            </button>\n            <button\n              type=\"button\"\n              class=\"text-primary-foreground/90 hover:bg-primary-foreground/15 inline-flex size-8 cursor-pointer items-center justify-center rounded-md transition\"\n              (click)=\"close()\"\n              title=\"{{ 'i18n_z_ui_chat_ai_close' | translate }}\">\n              <z-icon zType=\"lucideChevronDown\" zSize=\"18\" />\n            </button>\n          </div>\n        </div>\n      </header>\n\n      <div class=\"z-chat-lower-shell\">\n        <ng-scrollbar\n          #messagesScrollbar\n          (afterInit)=\"onMessagesScrollbarInit()\"\n          class=\"z-chat-scrollbar z-chat-content-surface flex-1 overflow-x-hidden\"\n          track=\"vertical\"\n          orientation=\"vertical\"\n          appearance=\"compact\"\n          visibility=\"hover\">\n          <div class=\"z-chat-messages\">\n            @if (hasMessages()) {\n              @for (item of zMessages(); track item.id) {\n                <div\n                  class=\"z-chat-message z-chat-message--enter\"\n                  [class.justify-end]=\"item.role === 'user'\"\n                  [class.justify-start]=\"item.role === 'assistant'\">\n                  <div\n                    class=\"z-chat-message-bubble max-w-[88%] min-w-0 rounded-2xl px-3 py-2.5 text-sm leading-5 [overflow-wrap:anywhere] break-all shadow-xs\"\n                    [class.bg-primary]=\"item.role === 'user'\"\n                    [class.text-primary-foreground]=\"item.role === 'user'\"\n                    [class.rounded-br-md]=\"item.role === 'user'\"\n                    [class.bg-background]=\"item.role === 'assistant'\"\n                    [class.border-border/60]=\"item.role === 'assistant'\"\n                    [class.text-foreground]=\"item.role === 'assistant'\"\n                    [class.rounded-bl-md]=\"item.role === 'assistant'\"\n                    [class.border]=\"item.role === 'assistant'\">\n                    @if (item.files && item.files.length > 0) {\n                      <div class=\"mb-2 flex flex-col gap-1.5\">\n                        @for (file of item.files; track file.id) {\n                          <div\n                            class=\"flex items-center gap-2 rounded-[0.5rem] px-2 py-1.5 text-xs\"\n                            [class.bg-white/15]=\"item.role === 'user'\"\n                            [class.bg-muted/40]=\"item.role === 'assistant'\">\n                            @if (isImageAttachment(file) && file.previewUrl) {\n                              <img\n                                [src]=\"file.previewUrl\"\n                                [alt]=\"file.name\"\n                                class=\"size-8 cursor-pointer rounded-[0.5rem] object-cover\"\n                                (click)=\"openImagePreview(file)\"\n                                title=\"Click to preview\" />\n                            } @else {\n                              <span\n                                class=\"bg-background/80 text-muted-foreground inline-flex size-8 items-center justify-center rounded-[0.5rem]\"\n                                [class.bg-white/20]=\"item.role === 'user'\"\n                                [class.text-white]=\"item.role === 'user'\">\n                                <z-icon zType=\"lucideFileText\" zSize=\"14\" />\n                              </span>\n                            }\n                            <div class=\"min-w-0 flex-1\">\n                              <p class=\"truncate text-[0.6875rem] font-medium\">{{ file.name }}</p>\n                              <p class=\"truncate text-[0.625rem] opacity-80\">{{ formatFileSize(file.size) }}</p>\n                            </div>\n                          </div>\n                        }\n                      </div>\n                    }\n                    {{ item.content }}\n                  </div>\n                </div>\n              }\n            } @else if (showEmptyState()) {\n              <div class=\"flex h-full min-h-60 flex-col items-center justify-center px-2 text-center\">\n                <div\n                  class=\"from-primary/20 to-primary/5 mb-3 inline-flex size-14 items-center justify-center rounded-full bg-gradient-to-br\">\n                  <z-icon zType=\"lucideBot\" zSize=\"28\" class=\"text-primary\" />\n                </div>\n                <h4 class=\"text-foreground text-sm font-semibold\">{{ 'i18n_z_ui_chat_ai_empty_title' | translate }}</h4>\n                <p class=\"text-muted-foreground mt-1 text-xs\">{{ 'i18n_z_ui_chat_ai_empty_desc' | translate }}</p>\n\n                @if (zSuggestions().length > 0) {\n                  <div class=\"mt-4 flex w-full flex-col gap-2\">\n                    @for (item of zSuggestions(); track item.label) {\n                      <button\n                        type=\"button\"\n                        class=\"z-chat-suggestion-item bg-background/95 hover:bg-background border-border/60 text-foreground flex w-full cursor-pointer items-center gap-2 rounded-xl border px-3 py-2 text-left text-xs transition hover:shadow-sm\"\n                        [style.animation-delay.ms]=\"$index * 70\"\n                        (click)=\"onSuggestionSelect(item)\">\n                        @if (item.icon) {\n                          <z-icon [zType]=\"item.icon!\" zSize=\"14\" class=\"text-primary shrink-0\" />\n                        }\n                        <span class=\"line-clamp-2\">{{ item.label | translate }}</span>\n                      </button>\n                    }\n                  </div>\n                }\n              </div>\n            }\n\n            @if (isTyping()) {\n              <div class=\"z-chat-message z-chat-message--enter justify-start\">\n                <div class=\"bg-background border-border/60 rounded-2xl rounded-bl-md border px-3 py-2\">\n                  <div class=\"flex items-center gap-1\">\n                    <span class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"></span>\n                    <span\n                      class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"\n                      style=\"animation-delay: 0.15s\"></span>\n                    <span\n                      class=\"bg-muted-foreground/60 inline-block size-1.5 animate-bounce rounded-full\"\n                      style=\"animation-delay: 0.3s\"></span>\n                  </div>\n                </div>\n              </div>\n            }\n          </div>\n        </ng-scrollbar>\n\n        <footer class=\"z-chat-footer-surface p-3\">\n          @if (attachments().length > 0) {\n            <div class=\"mb-2 flex max-h-32 flex-col gap-2 overflow-y-auto pr-1\">\n              @for (file of attachments(); track file.id) {\n                <div\n                  class=\"bg-muted/45 border-border/55 relative flex w-full items-center gap-2 rounded-[0.5rem] border px-2 py-1.5\">\n                  @if (isImageAttachment(file) && file.previewUrl) {\n                    <img\n                      [src]=\"file.previewUrl\"\n                      [alt]=\"file.name\"\n                      class=\"size-8 shrink-0 cursor-pointer rounded-[0.5rem] object-cover\"\n                      (click)=\"openImagePreview(file)\"\n                      title=\"Click to preview\" />\n                  } @else {\n                    <span\n                      class=\"bg-background text-muted-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-[0.5rem]\">\n                      <z-icon zType=\"lucideFileText\" zSize=\"14\" />\n                    </span>\n                  }\n                  <div class=\"min-w-0 flex-1\">\n                    <p class=\"truncate text-[0.6875rem] font-medium\">{{ file.name }}</p>\n                    <p class=\"text-muted-foreground truncate text-[0.625rem]\">{{ formatFileSize(file.size) }}</p>\n                  </div>\n                  <button\n                    type=\"button\"\n                    class=\"bg-background/80 hover:bg-background text-muted-foreground inline-flex size-5 cursor-pointer items-center justify-center rounded-full transition\"\n                    (click)=\"removeAttachment(file.id)\">\n                    <z-icon zType=\"lucideX\" zSize=\"12\" />\n                  </button>\n                </div>\n              }\n            </div>\n          }\n\n          <div class=\"z-chat-composer-shell\">\n            <div class=\"z-chat-composer-main\" [class.z-chat-composer__field--overflow]=\"isComposerOverflowing()\">\n              <textarea\n                #chatInput\n                class=\"z-chat-composer-textarea\"\n                [placeholder]=\"zPlaceholder() | translate\"\n                [disabled]=\"zDisabled()\"\n                [ngModel]=\"draftMessage()\"\n                (ngModelChange)=\"draftMessage.set($event)\"\n                (input)=\"onTextareaInput($event)\"\n                (paste)=\"onTextareaPaste($event)\"\n                (keydown)=\"onInputKeydown($event)\"\n                rows=\"3\"></textarea>\n            </div>\n\n            <div class=\"z-chat-composer-toolbar\">\n              <div class=\"z-chat-composer-toolbar-left\">\n                @if (zAllowAttachments()) {\n                  <input\n                    #fileInput\n                    type=\"file\"\n                    class=\"hidden\"\n                    [attr.accept]=\"zAcceptedFiles()\"\n                    multiple\n                    (change)=\"onFileChange($event)\" />\n                  <button\n                    type=\"button\"\n                    class=\"z-chat-composer-tool-btn\"\n                    [disabled]=\"zDisabled()\"\n                    (click)=\"onClickAttach()\"\n                    title=\"{{ 'i18n_z_ui_chat_ai_attach' | translate }}\">\n                    <z-icon zType=\"lucidePlus\" zSize=\"18\" />\n                  </button>\n                }\n              </div>\n\n              <div class=\"z-chat-composer-toolbar-right\">\n                <button\n                  type=\"button\"\n                  class=\"z-chat-composer-send-btn\"\n                  [disabled]=\"!canSend()\"\n                  (click)=\"onSendMessage()\"\n                  title=\"{{ 'i18n_z_ui_chat_ai_send' | translate }}\">\n                  <z-icon\n                    [zType]=\"isTyping() ? 'lucideLoaderCircle' : zSendIcon()\"\n                    zSize=\"16\"\n                    [class]=\"isTyping() ? 'animate-spin' : ''\" />\n                </button>\n              </div>\n            </div>\n          </div>\n        </footer>\n      </div>\n\n      <z-modal\n        [zVisible]=\"isPreviewVisible()\"\n        [zTitle]=\"previewImage()?.name\"\n        [zDescription]=\"previewImageSizeLabel()\"\n        zWidth=\"min(92vw, 720px)\"\n        [zHideFooter]=\"true\"\n        [zMaskClosable]=\"true\"\n        zOverlay=\"blur\"\n        (zCancel)=\"closeImagePreview()\">\n        <div class=\"z-chat-preview-modal-body\">\n          <img [src]=\"previewImage()?.url\" [alt]=\"previewImage()?.name\" class=\"z-chat-preview-image\" />\n        </div>\n      </z-modal>\n    </section>\n\n    <button\n      type=\"button\"\n      class=\"pointer-events-auto cursor-pointer\"\n      [class]=\"fabClasses()\"\n      (click)=\"onToggle()\"\n      [attr.aria-expanded]=\"zOpen()\"\n      [attr.aria-label]=\"'i18n_z_ui_chat_ai_toggle' | translate\"\n      title=\"{{ 'i18n_z_ui_chat_ai_toggle' | translate }}\">\n      @if (zShowPulse() && !zOpen()) {\n        <span class=\"bg-primary/30 absolute inset-0 animate-ping rounded-full\"></span>\n      }\n\n      @if (showRipple()) {\n        <span class=\"bg-primary-foreground/30 absolute inset-0 animate-ping rounded-full\"></span>\n      }\n\n      <z-icon\n        [zType]=\"zOpen() ? 'lucideX' : zFabIcon()\"\n        zSize=\"24\"\n        class=\"relative z-1 transition-transform duration-200\"\n        [class.rotate-180]=\"zOpen()\" />\n    </button>\n  </div>\n</div>\n", styles: [".z-chat textarea{scrollbar-width:thin}.z-chat-panel-shell{box-shadow:0 0 28px #00000024!important}:is(.dark,[data-theme=dark]) .z-chat-panel-shell{box-shadow:0 0 28px #00000057!important}.z-chat-composer__field--overflow:after{position:absolute;right:0;bottom:0;left:0;height:1rem;pointer-events:none;content:\"\";background:linear-gradient(to top,var(--background) 22%,transparent)}.z-chat-composer-shell{position:relative;display:flex;width:100%;flex-direction:column;border:1px solid color-mix(in oklab,var(--border) 82%,transparent);border-radius:1rem;background:linear-gradient(180deg,color-mix(in oklab,var(--card) 98%,var(--background) 2%),color-mix(in oklab,var(--card) 92%,var(--background) 8%));box-shadow:0 6px 18px #00000014;transition:box-shadow .2s ease}.z-chat-composer-shell:focus-within{box-shadow:0 6px 18px #00000014}:is(.dark,[data-theme=dark]) .z-chat-composer-shell{border-color:var(--border);background:linear-gradient(180deg,color-mix(in oklab,var(--card) 96%,var(--background) 4%),color-mix(in oklab,var(--card) 88%,var(--background) 12%));box-shadow:0 10px 24px #00000057}.z-chat-composer-main{position:relative;overflow:hidden;padding:.7rem .35rem .45rem .85rem}.z-chat-composer-textarea{width:100%;height:4.125rem;max-height:4.125rem;border:none;background:transparent;resize:none;overflow-x:hidden;font-size:.875rem;line-height:1.4rem;color:var(--foreground);outline:none;padding-right:.2rem;scrollbar-width:thin;overflow-wrap:anywhere;word-break:break-word}.z-chat-composer-textarea::placeholder{color:var(--muted-foreground)}.z-chat-composer-textarea::-webkit-scrollbar{width:.375rem}.z-chat-composer-textarea::-webkit-scrollbar-track{background:transparent}.z-chat-composer-textarea::-webkit-scrollbar-thumb{border-radius:62.4375rem;background:#64748b73}:is(.dark,[data-theme=dark]) .z-chat-composer-textarea::-webkit-scrollbar-thumb{background:#94a3b88c}.z-chat-composer-toolbar{display:flex;align-items:center;justify-content:space-between;border-top:.0625rem solid rgba(219,219,219,.6);padding:.55rem .7rem .65rem}:is(.dark,[data-theme=dark]) .z-chat-composer-toolbar{border-top-color:#00000038}.z-chat-composer-toolbar-left,.z-chat-composer-toolbar-right{display:flex;align-items:center}.z-chat-composer-tool-btn{display:inline-flex;height:1.75rem;width:1.75rem;cursor:pointer;align-items:center;justify-content:center;border-radius:.6rem;border:none;background:transparent;color:#374151;transition:background-color .2s ease}.z-chat-composer-tool-btn:hover{background:#0000000f}:is(.dark,[data-theme=dark]) .z-chat-composer-tool-btn{color:#e5e7ebe6}:is(.dark,[data-theme=dark]) .z-chat-composer-tool-btn:hover{background:#ffffff1a}.z-chat-composer-tool-btn:disabled{cursor:not-allowed;opacity:.5}.z-chat-composer-send-btn{display:inline-flex;height:2rem;width:2rem;cursor:pointer;align-items:center;justify-content:center;border-radius:62.4375rem;border:1px solid rgba(0,0,0,.1);background:var(--primary);color:var(--primary-foreground);box-shadow:0 2px 8px #0000002e,inset 0 1px #ffffff2e;transition:transform .15s ease,opacity .2s ease,box-shadow .2s ease}.z-chat-composer-send-btn:hover{transform:translateY(-.0625rem);box-shadow:0 4px 12px #00000038,inset 0 1px #ffffff38}.z-chat-composer-send-btn:disabled{cursor:not-allowed;opacity:.45;box-shadow:none}.z-chat-scrollbar{contain:layout}.z-chat-content-surface{background:var(--card)}.z-chat-lower-shell{display:flex;min-height:0;flex:1;flex-direction:column;overflow:hidden;background:var(--card);color:var(--card-foreground);border:1px solid transparent;border-top:0;border-bottom-right-radius:1rem;border-bottom-left-radius:1rem}:is(.dark,[data-theme=dark]) .z-chat-lower-shell{border-color:var(--border);border-top:0}.z-chat-footer-surface{background:transparent;border-top:.0625rem solid color-mix(in oklab,var(--border) 70%,transparent)}:is(.dark,[data-theme=dark]) .z-chat-footer-surface{background:transparent;border-top-color:var(--border)}.z-chat-messages{min-height:100%;overflow-x:hidden;padding:.875rem .75rem;contain:content}.z-chat-message{display:flex;margin:.5rem 0;padding:0 2px;transform-origin:bottom center;contain:layout style}.z-chat-message-bubble{transform:translateZ(0);backface-visibility:hidden}.z-chat-message--enter{animation:z-chat-message-push-in .3s ease-out;will-change:transform,opacity}.z-chat-suggestion-item{animation:z-chat-suggestion-reveal .28s ease-out both;will-change:transform,opacity}.z-chat-preview-modal-body{display:flex;align-items:center;justify-content:center;max-height:min(70vh,40rem);padding:.25rem}.z-chat-preview-image{max-width:100%;max-height:min(66vh,37.5rem);border-radius:.5rem;object-fit:contain}@keyframes z-chat-message-push-in{0%{opacity:0;transform:translateY(.9375rem) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes z-chat-suggestion-reveal{0%{opacity:0;transform:translateY(.5rem) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
        }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOpen", required: false }] }, { type: i0.Output, args: ["zOpenChange"] }], zMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMessages", required: false }] }, { type: i0.Output, args: ["zMessagesChange"] }], zTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTitle", required: false }] }], zSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSubtitle", required: false }] }], zPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPlaceholder", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOffset", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zSuggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSuggestions", required: false }] }], zShowSuggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowSuggestions", required: false }] }], zShowPulse: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowPulse", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLoading", required: false }] }], zAllowAttachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowAttachments", required: false }] }], zAcceptedFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAcceptedFiles", required: false }] }], zAutoReply: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoReply", required: false }] }], zAutoReplyDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAutoReplyDelay", required: false }] }], zFabIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFabIcon", required: false }] }], zBotIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zBotIcon", required: false }] }], zSendIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSendIcon", required: false }] }], zSend: [{ type: i0.Output, args: ["zSend"] }], zResponse: [{ type: i0.Output, args: ["zResponse"] }], zToggle: [{ type: i0.Output, args: ["zToggle"] }], zClear: [{ type: i0.Output, args: ["zClear"] }], _messagesScrollbarRef: [{ type: i0.ViewChild, args: ['messagesScrollbar', { isSignal: true }] }], _chatInputRef: [{ type: i0.ViewChild, args: ['chatInput', { isSignal: true }] }], _fileInputRef: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });

/**
 * Generated bundle index. Do not edit.
 */

export { ZChatComponent, zChatFabVariants, zChatPanelVariants, zChatWrapperVariants };
//# sourceMappingURL=shival99-z-ui-components-z-chat.mjs.map
