@shival99/z-ui 1.3.38 → 1.3.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shival99/z-ui",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.39",
|
|
4
4
|
"description": "Z-UI: Modern Angular UI Component Library - A comprehensive, high-performance design system built with Angular 20+, featuring 40+ customizable components with dark mode, accessibility, and enterprise-ready features.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -132,10 +132,6 @@
|
|
|
132
132
|
"types": "./types/shival99-z-ui-components-z-card.d.ts",
|
|
133
133
|
"default": "./fesm2022/shival99-z-ui-components-z-card.mjs"
|
|
134
134
|
},
|
|
135
|
-
"./components/z-chat-ai": {
|
|
136
|
-
"types": "./types/shival99-z-ui-components-z-chat-ai.d.ts",
|
|
137
|
-
"default": "./fesm2022/shival99-z-ui-components-z-chat-ai.mjs"
|
|
138
|
-
},
|
|
139
135
|
"./components/z-checkbox": {
|
|
140
136
|
"types": "./types/shival99-z-ui-components-z-checkbox.d.ts",
|
|
141
137
|
"default": "./fesm2022/shival99-z-ui-components-z-checkbox.mjs"
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, model, output, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import * as i1 from '@angular/forms';
|
|
4
|
-
import { FormsModule } from '@angular/forms';
|
|
5
|
-
import { TranslatePipe } from '@ngx-translate/core';
|
|
6
|
-
import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
|
|
7
|
-
import { zMergeClasses } from '@shival99/z-ui/utils';
|
|
8
|
-
import { cva } from 'class-variance-authority';
|
|
9
|
-
|
|
10
|
-
const zChatAiButtonWrapperVariants = cva(['z-chat-ai-button-wrapper', 'fixed z-[9999]'], {
|
|
11
|
-
variants: {
|
|
12
|
-
zPosition: {
|
|
13
|
-
'bottom-right': 'bottom-16 right-4',
|
|
14
|
-
'bottom-left': 'bottom-16 left-4',
|
|
15
|
-
'top-right': 'top-4 right-4',
|
|
16
|
-
'top-left': 'top-4 left-4',
|
|
17
|
-
},
|
|
18
|
-
zPulse: {
|
|
19
|
-
true: 'z-chat-ai-button-wrapper--pulse',
|
|
20
|
-
false: '',
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
defaultVariants: {
|
|
24
|
-
zPosition: 'bottom-right',
|
|
25
|
-
zPulse: true,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
const zChatAiButtonVariants = cva([
|
|
29
|
-
'z-chat-ai-button',
|
|
30
|
-
'relative flex items-center justify-center rounded-full cursor-pointer size-14',
|
|
31
|
-
'bg-primary text-primary-foreground shadow-lg',
|
|
32
|
-
'transition-all duration-300 ease-out',
|
|
33
|
-
'hover:scale-105 hover:shadow-xl',
|
|
34
|
-
'focus:outline-none focus-visible:ring-4 focus-visible:ring-primary/30',
|
|
35
|
-
]);
|
|
36
|
-
const zChatAiContainerVariants = cva([
|
|
37
|
-
'z-chat-ai-container',
|
|
38
|
-
'fixed z-[9998] flex flex-col w-96 h-[520px]',
|
|
39
|
-
'bg-background border border-border rounded-2xl shadow-2xl',
|
|
40
|
-
'overflow-hidden',
|
|
41
|
-
'transition-all duration-300 ease-out',
|
|
42
|
-
], {
|
|
43
|
-
variants: {
|
|
44
|
-
zPosition: {
|
|
45
|
-
'bottom-right': 'bottom-32 right-4',
|
|
46
|
-
'bottom-left': 'bottom-32 left-4',
|
|
47
|
-
'top-right': 'top-20 right-4',
|
|
48
|
-
'top-left': 'top-20 left-4',
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
defaultVariants: {
|
|
52
|
-
zPosition: 'bottom-right',
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
const zChatAiMessageVariants = cva([
|
|
56
|
-
'z-chat-ai-message',
|
|
57
|
-
'max-w-[85%] px-3.5 py-2.5 rounded-2xl',
|
|
58
|
-
'text-sm leading-relaxed',
|
|
59
|
-
'animate-in fade-in-0 slide-in-from-bottom-2 duration-300',
|
|
60
|
-
], {
|
|
61
|
-
variants: {
|
|
62
|
-
zType: {
|
|
63
|
-
user: ['ml-auto', 'bg-primary text-primary-foreground', 'rounded-br-md'],
|
|
64
|
-
bot: ['mr-auto', 'bg-muted text-foreground', 'rounded-bl-md'],
|
|
65
|
-
system: ['mx-auto', 'bg-muted/50 text-muted-foreground', 'text-xs text-center'],
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
defaultVariants: {
|
|
69
|
-
zType: 'bot',
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
const zChatAiSuggestionVariants = cva([
|
|
73
|
-
'z-chat-ai-suggestion',
|
|
74
|
-
'inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full',
|
|
75
|
-
'text-xs font-medium whitespace-nowrap cursor-pointer',
|
|
76
|
-
'border transition-all duration-200',
|
|
77
|
-
'hover:scale-105 active:scale-95',
|
|
78
|
-
], {
|
|
79
|
-
variants: {
|
|
80
|
-
zColor: {
|
|
81
|
-
default: 'bg-secondary text-secondary-foreground border-transparent hover:bg-secondary/80',
|
|
82
|
-
blue: 'bg-blue-100 text-blue-700 border-blue-200 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400 dark:border-blue-800',
|
|
83
|
-
green: 'bg-green-100 text-green-700 border-green-200 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400 dark:border-green-800',
|
|
84
|
-
purple: 'bg-purple-100 text-purple-700 border-purple-200 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400 dark:border-purple-800',
|
|
85
|
-
orange: 'bg-orange-100 text-orange-700 border-orange-200 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400 dark:border-orange-800',
|
|
86
|
-
pink: 'bg-pink-100 text-pink-700 border-pink-200 hover:bg-pink-200 dark:bg-pink-900/30 dark:text-pink-400 dark:border-pink-800',
|
|
87
|
-
cyan: 'bg-cyan-100 text-cyan-700 border-cyan-200 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400 dark:border-cyan-800',
|
|
88
|
-
yellow: 'bg-yellow-100 text-yellow-700 border-yellow-200 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400 dark:border-yellow-800',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
defaultVariants: {
|
|
92
|
-
zColor: 'default',
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
const zChatAiInputVariants = cva([
|
|
96
|
-
'flex w-full items-center gap-2 rounded-[6px] border border-input bg-white px-2 py-1.5 shadow-xs',
|
|
97
|
-
'transition-[border-color,box-shadow,background-color] duration-200',
|
|
98
|
-
'dark:bg-input/30 dark:border-input',
|
|
99
|
-
'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]',
|
|
100
|
-
]);
|
|
101
|
-
|
|
102
|
-
class ZChatAiComponent {
|
|
103
|
-
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
|
|
104
|
-
zPosition = input('bottom-right', ...(ngDevMode ? [{ debugName: "zPosition" }] : []));
|
|
105
|
-
zPulse = input(true, ...(ngDevMode ? [{ debugName: "zPulse" }] : []));
|
|
106
|
-
zMessages = input([], ...(ngDevMode ? [{ debugName: "zMessages" }] : []));
|
|
107
|
-
zSuggestions = input([], ...(ngDevMode ? [{ debugName: "zSuggestions" }] : []));
|
|
108
|
-
zConfig = input({}, ...(ngDevMode ? [{ debugName: "zConfig" }] : []));
|
|
109
|
-
zTyping = input(false, ...(ngDevMode ? [{ debugName: "zTyping" }] : []));
|
|
110
|
-
zOpen = model(false, ...(ngDevMode ? [{ debugName: "zOpen" }] : []));
|
|
111
|
-
zOnSend = output();
|
|
112
|
-
zOnSuggestionClick = output();
|
|
113
|
-
zOnAttachmentRemove = output();
|
|
114
|
-
inputValue = signal('', ...(ngDevMode ? [{ debugName: "inputValue" }] : []));
|
|
115
|
-
attachments = signal([], ...(ngDevMode ? [{ debugName: "attachments" }] : []));
|
|
116
|
-
fileInputRef = viewChild('fileInput', ...(ngDevMode ? [{ debugName: "fileInputRef" }] : []));
|
|
117
|
-
messagesContainerRef = viewChild('messagesContainer', ...(ngDevMode ? [{ debugName: "messagesContainerRef" }] : []));
|
|
118
|
-
buttonWrapperClasses = computed(() => zMergeClasses(zChatAiButtonWrapperVariants({
|
|
119
|
-
zPosition: this.zPosition(),
|
|
120
|
-
zPulse: this.zPulse(),
|
|
121
|
-
})), ...(ngDevMode ? [{ debugName: "buttonWrapperClasses" }] : []));
|
|
122
|
-
buttonClasses = computed(() => zMergeClasses(zChatAiButtonVariants()), ...(ngDevMode ? [{ debugName: "buttonClasses" }] : []));
|
|
123
|
-
containerClasses = computed(() => zMergeClasses(zChatAiContainerVariants({
|
|
124
|
-
zPosition: this.zPosition(),
|
|
125
|
-
}), this.class()), ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
126
|
-
inputClasses = computed(() => zMergeClasses(zChatAiInputVariants()), ...(ngDevMode ? [{ debugName: "inputClasses" }] : []));
|
|
127
|
-
config = computed(() => ({
|
|
128
|
-
title: this.zConfig().title ?? 'AI Assistant',
|
|
129
|
-
subtitle: this.zConfig().subtitle ?? 'How can I help you today?',
|
|
130
|
-
placeholder: this.zConfig().placeholder ?? 'Type a message...',
|
|
131
|
-
welcomeMessage: this.zConfig().welcomeMessage,
|
|
132
|
-
avatarUrl: this.zConfig().avatarUrl,
|
|
133
|
-
botName: this.zConfig().botName ?? 'Assistant',
|
|
134
|
-
maxFileSize: this.zConfig().maxFileSize ?? 10 * 1024 * 1024,
|
|
135
|
-
allowedFileTypes: this.zConfig().allowedFileTypes ?? ['image/*', '.pdf', '.doc', '.docx'],
|
|
136
|
-
maxFiles: this.zConfig().maxFiles ?? 5,
|
|
137
|
-
}), ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
138
|
-
toggleOpen() {
|
|
139
|
-
this.zOpen.update(v => !v);
|
|
140
|
-
}
|
|
141
|
-
close() {
|
|
142
|
-
this.zOpen.set(false);
|
|
143
|
-
}
|
|
144
|
-
getMessageClasses(type) {
|
|
145
|
-
return zChatAiMessageVariants({ zType: type });
|
|
146
|
-
}
|
|
147
|
-
getSuggestionClasses(color) {
|
|
148
|
-
return zChatAiSuggestionVariants({ zColor: color ?? 'default' });
|
|
149
|
-
}
|
|
150
|
-
sendMessage() {
|
|
151
|
-
const message = this.inputValue().trim();
|
|
152
|
-
if (!message && this.attachments().length === 0) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
this.zOnSend.emit({
|
|
156
|
-
message,
|
|
157
|
-
attachments: [...this.attachments()],
|
|
158
|
-
});
|
|
159
|
-
this.inputValue.set('');
|
|
160
|
-
this.attachments.set([]);
|
|
161
|
-
}
|
|
162
|
-
onKeydown(event) {
|
|
163
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
164
|
-
event.preventDefault();
|
|
165
|
-
this.sendMessage();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
onSuggestionClick(suggestion) {
|
|
169
|
-
this.zOnSuggestionClick.emit(suggestion);
|
|
170
|
-
}
|
|
171
|
-
openFileDialog() {
|
|
172
|
-
this.fileInputRef()?.nativeElement.click();
|
|
173
|
-
}
|
|
174
|
-
onFileSelect(event) {
|
|
175
|
-
const input = event.target;
|
|
176
|
-
const { files } = input;
|
|
177
|
-
if (!files) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
const config = this.config();
|
|
181
|
-
const currentAttachments = this.attachments();
|
|
182
|
-
if (currentAttachments.length + files.length > config.maxFiles) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const newAttachments = [];
|
|
186
|
-
for (let i = 0; i < files.length; i++) {
|
|
187
|
-
const file = files[i];
|
|
188
|
-
if (file.size > config.maxFileSize) {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
newAttachments.push({
|
|
192
|
-
id: crypto.randomUUID(),
|
|
193
|
-
name: file.name,
|
|
194
|
-
size: file.size,
|
|
195
|
-
type: file.type,
|
|
196
|
-
status: 'uploaded',
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
this.attachments.update(att => [...att, ...newAttachments]);
|
|
200
|
-
input.value = '';
|
|
201
|
-
}
|
|
202
|
-
removeAttachment(attachment) {
|
|
203
|
-
this.attachments.update(att => att.filter(a => a.id !== attachment.id));
|
|
204
|
-
this.zOnAttachmentRemove.emit(attachment);
|
|
205
|
-
}
|
|
206
|
-
formatFileSize(bytes) {
|
|
207
|
-
if (bytes < 1024) {
|
|
208
|
-
return bytes + ' B';
|
|
209
|
-
}
|
|
210
|
-
if (bytes < 1024 * 1024) {
|
|
211
|
-
return (bytes / 1024).toFixed(1) + ' KB';
|
|
212
|
-
}
|
|
213
|
-
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
214
|
-
}
|
|
215
|
-
scrollToBottom() {
|
|
216
|
-
const container = this.messagesContainerRef()?.nativeElement;
|
|
217
|
-
if (container) {
|
|
218
|
-
container.scrollTop = container.scrollHeight;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZChatAiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
222
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZChatAiComponent, isStandalone: true, selector: "z-chat-ai", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zPulse: { classPropertyName: "zPulse", publicName: "zPulse", isSignal: true, isRequired: false, transformFunction: null }, zMessages: { classPropertyName: "zMessages", publicName: "zMessages", isSignal: true, isRequired: false, transformFunction: null }, zSuggestions: { classPropertyName: "zSuggestions", publicName: "zSuggestions", isSignal: true, isRequired: false, transformFunction: null }, zConfig: { classPropertyName: "zConfig", publicName: "zConfig", isSignal: true, isRequired: false, transformFunction: null }, zTyping: { classPropertyName: "zTyping", publicName: "zTyping", isSignal: true, isRequired: false, transformFunction: null }, zOpen: { classPropertyName: "zOpen", publicName: "zOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOpen: "zOpenChange", zOnSend: "zOnSend", zOnSuggestionClick: "zOnSuggestionClick", zOnAttachmentRemove: "zOnAttachmentRemove" }, host: { classAttribute: "z-chat-ai" }, viewQueries: [{ propertyName: "fileInputRef", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }, { propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], exportAs: ["zChatAi"], ngImport: i0, template: "<div class=\"z-chat-ai-button-wrapper\" [class]=\"buttonWrapperClasses()\">\n <button\n type=\"button\"\n [class]=\"buttonClasses()\"\n (click)=\"toggleOpen()\"\n [attr.aria-expanded]=\"zOpen()\"\n aria-label=\"Toggle chat\">\n <z-icon\n [zType]=\"zOpen() ? 'lucideX' : 'lucideMessageCircle'\"\n zSize=\"24\"\n class=\"transition-transform duration-300\"\n [class.rotate-90]=\"zOpen()\" />\n </button>\n</div>\n\n@if (zOpen()) {\n <div [class]=\"containerClasses()\">\n <div class=\"z-chat-ai-header border-border bg-muted/30 flex items-center gap-3 border-b p-4\">\n @if (config().avatarUrl) {\n <img [src]=\"config().avatarUrl\" [alt]=\"config().botName\" class=\"size-10 rounded-full object-cover\" />\n } @else {\n <div class=\"bg-primary/10 flex size-10 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideBot\" zSize=\"20\" class=\"text-primary\" />\n </div>\n }\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"truncate text-sm font-semibold\">{{ config().title }}</h3>\n <p class=\"text-muted-foreground truncate text-xs\">{{ config().subtitle }}</p>\n </div>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-full transition-colors\"\n (click)=\"close()\"\n aria-label=\"Close chat\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n </div>\n\n <div #messagesContainer class=\"z-chat-ai-body flex-1 space-y-3 overflow-y-auto p-4\">\n @if (config().welcomeMessage && zMessages().length === 0) {\n <div class=\"py-8 text-center\">\n <div class=\"bg-primary/10 mx-auto mb-4 flex size-16 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideSparkles\" zSize=\"28\" class=\"text-primary\" />\n </div>\n <p class=\"text-muted-foreground text-sm\">{{ config().welcomeMessage }}</p>\n </div>\n }\n\n @for (message of zMessages(); track message.id) {\n <div [class]=\"getMessageClasses(message.type)\">\n <div class=\"whitespace-pre-wrap\">{{ message.content }}</div>\n @if (message.attachments?.length) {\n <div class=\"mt-2 flex flex-wrap gap-2\">\n @for (attachment of message.attachments; track attachment.id) {\n <div class=\"flex items-center gap-1.5 rounded bg-black/10 px-2 py-1 text-xs\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (zTyping()) {\n <div class=\"z-chat-ai-typing bg-muted mr-auto flex items-center gap-1 rounded-2xl rounded-bl-md px-4 py-3\">\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n </div>\n }\n </div>\n\n @if (zSuggestions().length > 0 && zMessages().length === 0) {\n <div class=\"z-chat-ai-suggestions px-4 pb-2\">\n <div class=\"scrollbar-hide flex gap-2 overflow-x-auto pb-2\">\n @for (suggestion of zSuggestions(); track suggestion.id) {\n <button\n type=\"button\"\n [class]=\"getSuggestionClasses(suggestion.color)\"\n (click)=\"onSuggestionClick(suggestion)\">\n @if (suggestion.icon) {\n <z-icon [zType]=\"$any(suggestion.icon)\" zSize=\"14\" />\n }\n {{ suggestion.label }}\n </button>\n }\n </div>\n </div>\n }\n\n <div class=\"z-chat-ai-footer border-border border-t p-4\">\n @if (attachments().length > 0) {\n <div class=\"mb-3 flex flex-wrap gap-2\">\n @for (attachment of attachments(); track attachment.id) {\n <div class=\"bg-muted flex items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs\">\n <z-icon zType=\"lucideFile\" zSize=\"14\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n <span class=\"text-muted-foreground\">({{ formatFileSize(attachment.size) }})</span>\n <button\n type=\"button\"\n class=\"hover:bg-destructive/20 text-muted-foreground hover:text-destructive flex size-4 items-center justify-center rounded-full transition-colors\"\n (click)=\"removeAttachment(attachment)\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n }\n\n <div [class]=\"inputClasses()\">\n <input\n #fileInput\n type=\"file\"\n class=\"hidden\"\n [accept]=\"config().allowedFileTypes.join(',')\"\n multiple\n (change)=\"onFileSelect($event)\" />\n <button\n type=\"button\"\n class=\"hover:bg-muted text-muted-foreground hover:text-foreground flex size-8 shrink-0 items-center justify-center rounded-md transition-colors\"\n (click)=\"openFileDialog()\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_attach' | translate\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"18\" />\n </button>\n <input\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [placeholder]=\"config().placeholder\"\n [(ngModel)]=\"inputValue\"\n (keydown)=\"onKeydown($event)\" />\n <button\n type=\"button\"\n class=\"bg-primary text-primary-foreground hover:bg-primary/90 flex size-8 shrink-0 items-center justify-center rounded-md transition-colors disabled:cursor-not-allowed disabled:opacity-50\"\n (click)=\"sendMessage()\"\n [disabled]=\"!inputValue().trim() && attachments().length === 0\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_send' | translate\">\n <z-icon zType=\"lucideSend\" zSize=\"16\" />\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".z-chat-ai{display:contents}.z-chat-ai-button-wrapper{position:relative}.z-chat-ai-button-wrapper:before,.z-chat-ai-button-wrapper:after{content:\"\";position:absolute;top:50%;left:50%;width:100px;height:100px;border-radius:50%;background:radial-gradient(circle,hsl(var(--primary)/.6) 0%,hsl(var(--primary)/.3) 40%,hsl(var(--primary)/.1) 70%,transparent 100%);transform:translate(-50%,-50%) scale(.7);opacity:0;pointer-events:none;z-index:-1}.z-chat-ai-button-wrapper--pulse:before{animation:z-chat-ai-pulse-wave 2.5s infinite ease-out}.z-chat-ai-button-wrapper--pulse:after{animation:z-chat-ai-pulse-wave 2.5s infinite ease-out;animation-delay:1.25s;background:radial-gradient(circle,hsl(var(--primary)/.4) 0%,hsl(var(--primary)/.2) 50%,hsl(var(--primary)/.05) 80%,transparent 100%)}.z-chat-ai-button:before{content:\"\";position:absolute;inset:-3px;border-radius:50%;border:2px solid hsl(var(--primary)/.6);opacity:0;animation:z-chat-ai-border-pulse-1 2.5s infinite ease-out}.z-chat-ai-button:after{content:\"\";position:absolute;inset:-6px;border-radius:50%;border:1px solid hsl(var(--primary)/.4);opacity:0;animation:z-chat-ai-border-pulse-2 2.5s infinite ease-out;animation-delay:.3s}.z-chat-ai-container{animation:z-chat-ai-slide-up .3s ease-out}.z-chat-ai-body{scrollbar-width:thin;scrollbar-color:hsl(var(--border)) transparent}.z-chat-ai-body::-webkit-scrollbar{width:6px}.z-chat-ai-body::-webkit-scrollbar-track{background:transparent}.z-chat-ai-body::-webkit-scrollbar-thumb{background:hsl(var(--border));border-radius:3px}.z-chat-ai-typing{min-height:32px}.z-chat-ai-typing-dot{width:8px;height:8px;border-radius:50%;background:hsl(var(--muted-foreground));animation:z-chat-ai-typing-bounce 1.4s ease-in-out infinite}.z-chat-ai-typing-dot:nth-child(1){animation-delay:0s}.z-chat-ai-typing-dot:nth-child(2){animation-delay:.2s}.z-chat-ai-typing-dot:nth-child(3){animation-delay:.4s}.z-chat-ai-suggestions .scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.z-chat-ai-suggestions .scrollbar-hide::-webkit-scrollbar{display:none}@keyframes z-chat-ai-pulse-wave{0%{transform:translate(-50%,-50%) scale(.7);opacity:0}10%{opacity:1}30%{transform:translate(-50%,-50%) scale(.85);opacity:.8}60%{transform:translate(-50%,-50%) scale(.95);opacity:.3}90%{transform:translate(-50%,-50%) scale(1);opacity:.1}to{transform:translate(-50%,-50%) scale(1);opacity:0}}@keyframes z-chat-ai-border-pulse-1{0%{opacity:0;transform:scale(1)}20%{opacity:1}60%{opacity:.6;transform:scale(1.05)}to{opacity:0;transform:scale(1.1)}}@keyframes z-chat-ai-border-pulse-2{0%{opacity:0;transform:scale(1)}15%{opacity:.8}50%{opacity:.4;transform:scale(1.05)}to{opacity:0;transform:scale(1.1)}}@keyframes z-chat-ai-slide-up{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes z-chat-ai-typing-bounce{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-8px);opacity:1}}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { 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: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
223
|
-
}
|
|
224
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZChatAiComponent, decorators: [{
|
|
225
|
-
type: Component,
|
|
226
|
-
args: [{ selector: 'z-chat-ai', imports: [ZIconComponent, TranslatePipe, FormsModule], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
227
|
-
class: 'z-chat-ai',
|
|
228
|
-
}, exportAs: 'zChatAi', template: "<div class=\"z-chat-ai-button-wrapper\" [class]=\"buttonWrapperClasses()\">\n <button\n type=\"button\"\n [class]=\"buttonClasses()\"\n (click)=\"toggleOpen()\"\n [attr.aria-expanded]=\"zOpen()\"\n aria-label=\"Toggle chat\">\n <z-icon\n [zType]=\"zOpen() ? 'lucideX' : 'lucideMessageCircle'\"\n zSize=\"24\"\n class=\"transition-transform duration-300\"\n [class.rotate-90]=\"zOpen()\" />\n </button>\n</div>\n\n@if (zOpen()) {\n <div [class]=\"containerClasses()\">\n <div class=\"z-chat-ai-header border-border bg-muted/30 flex items-center gap-3 border-b p-4\">\n @if (config().avatarUrl) {\n <img [src]=\"config().avatarUrl\" [alt]=\"config().botName\" class=\"size-10 rounded-full object-cover\" />\n } @else {\n <div class=\"bg-primary/10 flex size-10 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideBot\" zSize=\"20\" class=\"text-primary\" />\n </div>\n }\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"truncate text-sm font-semibold\">{{ config().title }}</h3>\n <p class=\"text-muted-foreground truncate text-xs\">{{ config().subtitle }}</p>\n </div>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-full transition-colors\"\n (click)=\"close()\"\n aria-label=\"Close chat\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n </div>\n\n <div #messagesContainer class=\"z-chat-ai-body flex-1 space-y-3 overflow-y-auto p-4\">\n @if (config().welcomeMessage && zMessages().length === 0) {\n <div class=\"py-8 text-center\">\n <div class=\"bg-primary/10 mx-auto mb-4 flex size-16 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideSparkles\" zSize=\"28\" class=\"text-primary\" />\n </div>\n <p class=\"text-muted-foreground text-sm\">{{ config().welcomeMessage }}</p>\n </div>\n }\n\n @for (message of zMessages(); track message.id) {\n <div [class]=\"getMessageClasses(message.type)\">\n <div class=\"whitespace-pre-wrap\">{{ message.content }}</div>\n @if (message.attachments?.length) {\n <div class=\"mt-2 flex flex-wrap gap-2\">\n @for (attachment of message.attachments; track attachment.id) {\n <div class=\"flex items-center gap-1.5 rounded bg-black/10 px-2 py-1 text-xs\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (zTyping()) {\n <div class=\"z-chat-ai-typing bg-muted mr-auto flex items-center gap-1 rounded-2xl rounded-bl-md px-4 py-3\">\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n </div>\n }\n </div>\n\n @if (zSuggestions().length > 0 && zMessages().length === 0) {\n <div class=\"z-chat-ai-suggestions px-4 pb-2\">\n <div class=\"scrollbar-hide flex gap-2 overflow-x-auto pb-2\">\n @for (suggestion of zSuggestions(); track suggestion.id) {\n <button\n type=\"button\"\n [class]=\"getSuggestionClasses(suggestion.color)\"\n (click)=\"onSuggestionClick(suggestion)\">\n @if (suggestion.icon) {\n <z-icon [zType]=\"$any(suggestion.icon)\" zSize=\"14\" />\n }\n {{ suggestion.label }}\n </button>\n }\n </div>\n </div>\n }\n\n <div class=\"z-chat-ai-footer border-border border-t p-4\">\n @if (attachments().length > 0) {\n <div class=\"mb-3 flex flex-wrap gap-2\">\n @for (attachment of attachments(); track attachment.id) {\n <div class=\"bg-muted flex items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs\">\n <z-icon zType=\"lucideFile\" zSize=\"14\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n <span class=\"text-muted-foreground\">({{ formatFileSize(attachment.size) }})</span>\n <button\n type=\"button\"\n class=\"hover:bg-destructive/20 text-muted-foreground hover:text-destructive flex size-4 items-center justify-center rounded-full transition-colors\"\n (click)=\"removeAttachment(attachment)\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n }\n\n <div [class]=\"inputClasses()\">\n <input\n #fileInput\n type=\"file\"\n class=\"hidden\"\n [accept]=\"config().allowedFileTypes.join(',')\"\n multiple\n (change)=\"onFileSelect($event)\" />\n <button\n type=\"button\"\n class=\"hover:bg-muted text-muted-foreground hover:text-foreground flex size-8 shrink-0 items-center justify-center rounded-md transition-colors\"\n (click)=\"openFileDialog()\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_attach' | translate\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"18\" />\n </button>\n <input\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [placeholder]=\"config().placeholder\"\n [(ngModel)]=\"inputValue\"\n (keydown)=\"onKeydown($event)\" />\n <button\n type=\"button\"\n class=\"bg-primary text-primary-foreground hover:bg-primary/90 flex size-8 shrink-0 items-center justify-center rounded-md transition-colors disabled:cursor-not-allowed disabled:opacity-50\"\n (click)=\"sendMessage()\"\n [disabled]=\"!inputValue().trim() && attachments().length === 0\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_send' | translate\">\n <z-icon zType=\"lucideSend\" zSize=\"16\" />\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [".z-chat-ai{display:contents}.z-chat-ai-button-wrapper{position:relative}.z-chat-ai-button-wrapper:before,.z-chat-ai-button-wrapper:after{content:\"\";position:absolute;top:50%;left:50%;width:100px;height:100px;border-radius:50%;background:radial-gradient(circle,hsl(var(--primary)/.6) 0%,hsl(var(--primary)/.3) 40%,hsl(var(--primary)/.1) 70%,transparent 100%);transform:translate(-50%,-50%) scale(.7);opacity:0;pointer-events:none;z-index:-1}.z-chat-ai-button-wrapper--pulse:before{animation:z-chat-ai-pulse-wave 2.5s infinite ease-out}.z-chat-ai-button-wrapper--pulse:after{animation:z-chat-ai-pulse-wave 2.5s infinite ease-out;animation-delay:1.25s;background:radial-gradient(circle,hsl(var(--primary)/.4) 0%,hsl(var(--primary)/.2) 50%,hsl(var(--primary)/.05) 80%,transparent 100%)}.z-chat-ai-button:before{content:\"\";position:absolute;inset:-3px;border-radius:50%;border:2px solid hsl(var(--primary)/.6);opacity:0;animation:z-chat-ai-border-pulse-1 2.5s infinite ease-out}.z-chat-ai-button:after{content:\"\";position:absolute;inset:-6px;border-radius:50%;border:1px solid hsl(var(--primary)/.4);opacity:0;animation:z-chat-ai-border-pulse-2 2.5s infinite ease-out;animation-delay:.3s}.z-chat-ai-container{animation:z-chat-ai-slide-up .3s ease-out}.z-chat-ai-body{scrollbar-width:thin;scrollbar-color:hsl(var(--border)) transparent}.z-chat-ai-body::-webkit-scrollbar{width:6px}.z-chat-ai-body::-webkit-scrollbar-track{background:transparent}.z-chat-ai-body::-webkit-scrollbar-thumb{background:hsl(var(--border));border-radius:3px}.z-chat-ai-typing{min-height:32px}.z-chat-ai-typing-dot{width:8px;height:8px;border-radius:50%;background:hsl(var(--muted-foreground));animation:z-chat-ai-typing-bounce 1.4s ease-in-out infinite}.z-chat-ai-typing-dot:nth-child(1){animation-delay:0s}.z-chat-ai-typing-dot:nth-child(2){animation-delay:.2s}.z-chat-ai-typing-dot:nth-child(3){animation-delay:.4s}.z-chat-ai-suggestions .scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.z-chat-ai-suggestions .scrollbar-hide::-webkit-scrollbar{display:none}@keyframes z-chat-ai-pulse-wave{0%{transform:translate(-50%,-50%) scale(.7);opacity:0}10%{opacity:1}30%{transform:translate(-50%,-50%) scale(.85);opacity:.8}60%{transform:translate(-50%,-50%) scale(.95);opacity:.3}90%{transform:translate(-50%,-50%) scale(1);opacity:.1}to{transform:translate(-50%,-50%) scale(1);opacity:0}}@keyframes z-chat-ai-border-pulse-1{0%{opacity:0;transform:scale(1)}20%{opacity:1}60%{opacity:.6;transform:scale(1.05)}to{opacity:0;transform:scale(1.1)}}@keyframes z-chat-ai-border-pulse-2{0%{opacity:0;transform:scale(1)}15%{opacity:.8}50%{opacity:.4;transform:scale(1.05)}to{opacity:0;transform:scale(1.1)}}@keyframes z-chat-ai-slide-up{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes z-chat-ai-typing-bounce{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-8px);opacity:1}}\n"] }]
|
|
229
|
-
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zPulse: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPulse", required: false }] }], zMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "zMessages", required: false }] }], zSuggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSuggestions", required: false }] }], zConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "zConfig", required: false }] }], zTyping: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTyping", required: false }] }], zOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOpen", required: false }] }, { type: i0.Output, args: ["zOpenChange"] }], zOnSend: [{ type: i0.Output, args: ["zOnSend"] }], zOnSuggestionClick: [{ type: i0.Output, args: ["zOnSuggestionClick"] }], zOnAttachmentRemove: [{ type: i0.Output, args: ["zOnAttachmentRemove"] }], fileInputRef: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }], messagesContainerRef: [{ type: i0.ViewChild, args: ['messagesContainer', { isSignal: true }] }] } });
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Generated bundle index. Do not edit.
|
|
233
|
-
*/
|
|
234
|
-
|
|
235
|
-
export { ZChatAiComponent, zChatAiButtonVariants, zChatAiButtonWrapperVariants, zChatAiContainerVariants, zChatAiInputVariants, zChatAiMessageVariants, zChatAiSuggestionVariants };
|
|
236
|
-
//# sourceMappingURL=shival99-z-ui-components-z-chat-ai.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shival99-z-ui-components-z-chat-ai.mjs","sources":["../../../../libs/core-ui/components/z-chat-ai/z-chat-ai.variants.ts","../../../../libs/core-ui/components/z-chat-ai/z-chat-ai.component.ts","../../../../libs/core-ui/components/z-chat-ai/z-chat-ai.component.html","../../../../libs/core-ui/components/z-chat-ai/shival99-z-ui-components-z-chat-ai.ts"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\n\nexport const zChatAiButtonWrapperVariants = cva(['z-chat-ai-button-wrapper', 'fixed z-[9999]'], {\n variants: {\n zPosition: {\n 'bottom-right': 'bottom-16 right-4',\n 'bottom-left': 'bottom-16 left-4',\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n },\n zPulse: {\n true: 'z-chat-ai-button-wrapper--pulse',\n false: '',\n },\n },\n defaultVariants: {\n zPosition: 'bottom-right',\n zPulse: true,\n },\n});\n\nexport type ZChatAiButtonWrapperVariants = VariantProps<typeof zChatAiButtonWrapperVariants>;\n\nexport const zChatAiButtonVariants = cva([\n 'z-chat-ai-button',\n 'relative flex items-center justify-center rounded-full cursor-pointer size-14',\n 'bg-primary text-primary-foreground shadow-lg',\n 'transition-all duration-300 ease-out',\n 'hover:scale-105 hover:shadow-xl',\n 'focus:outline-none focus-visible:ring-4 focus-visible:ring-primary/30',\n]);\n\nexport type ZChatAiButtonVariants = VariantProps<typeof zChatAiButtonVariants>;\n\nexport const zChatAiContainerVariants = cva(\n [\n 'z-chat-ai-container',\n 'fixed z-[9998] flex flex-col w-96 h-[520px]',\n 'bg-background border border-border rounded-2xl shadow-2xl',\n 'overflow-hidden',\n 'transition-all duration-300 ease-out',\n ],\n {\n variants: {\n zPosition: {\n 'bottom-right': 'bottom-32 right-4',\n 'bottom-left': 'bottom-32 left-4',\n 'top-right': 'top-20 right-4',\n 'top-left': 'top-20 left-4',\n },\n },\n defaultVariants: {\n zPosition: 'bottom-right',\n },\n }\n);\n\nexport type ZChatAiContainerVariants = VariantProps<typeof zChatAiContainerVariants>;\n\nexport const zChatAiMessageVariants = cva(\n [\n 'z-chat-ai-message',\n 'max-w-[85%] px-3.5 py-2.5 rounded-2xl',\n 'text-sm leading-relaxed',\n 'animate-in fade-in-0 slide-in-from-bottom-2 duration-300',\n ],\n {\n variants: {\n zType: {\n user: ['ml-auto', 'bg-primary text-primary-foreground', 'rounded-br-md'],\n bot: ['mr-auto', 'bg-muted text-foreground', 'rounded-bl-md'],\n system: ['mx-auto', 'bg-muted/50 text-muted-foreground', 'text-xs text-center'],\n },\n },\n defaultVariants: {\n zType: 'bot',\n },\n }\n);\n\nexport type ZChatAiMessageVariants = VariantProps<typeof zChatAiMessageVariants>;\n\nexport const zChatAiSuggestionVariants = cva(\n [\n 'z-chat-ai-suggestion',\n 'inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full',\n 'text-xs font-medium whitespace-nowrap cursor-pointer',\n 'border transition-all duration-200',\n 'hover:scale-105 active:scale-95',\n ],\n {\n variants: {\n zColor: {\n default: 'bg-secondary text-secondary-foreground border-transparent hover:bg-secondary/80',\n blue: 'bg-blue-100 text-blue-700 border-blue-200 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400 dark:border-blue-800',\n green:\n 'bg-green-100 text-green-700 border-green-200 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400 dark:border-green-800',\n purple:\n 'bg-purple-100 text-purple-700 border-purple-200 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400 dark:border-purple-800',\n orange:\n 'bg-orange-100 text-orange-700 border-orange-200 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400 dark:border-orange-800',\n pink: 'bg-pink-100 text-pink-700 border-pink-200 hover:bg-pink-200 dark:bg-pink-900/30 dark:text-pink-400 dark:border-pink-800',\n cyan: 'bg-cyan-100 text-cyan-700 border-cyan-200 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400 dark:border-cyan-800',\n yellow:\n 'bg-yellow-100 text-yellow-700 border-yellow-200 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400 dark:border-yellow-800',\n },\n },\n defaultVariants: {\n zColor: 'default',\n },\n }\n);\n\nexport type ZChatAiSuggestionVariants = VariantProps<typeof zChatAiSuggestionVariants>;\n\nexport const zChatAiInputVariants = cva([\n 'flex w-full items-center gap-2 rounded-[6px] border border-input bg-white px-2 py-1.5 shadow-xs',\n 'transition-[border-color,box-shadow,background-color] duration-200',\n 'dark:bg-input/30 dark:border-input',\n 'focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]',\n]);\n\nexport type ZChatAiInputVariants = VariantProps<typeof zChatAiInputVariants>;\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n ElementRef,\n input,\n model,\n output,\n signal,\n ViewEncapsulation,\n viewChild,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { TranslatePipe } from '@ngx-translate/core';\nimport { ZIconComponent } from '@shival99/z-ui/components/z-icon';\nimport { zMergeClasses } from '@shival99/z-ui/utils';\nimport type { ClassValue } from 'clsx';\nimport type {\n ZChatAiMessage,\n ZChatAiSuggestion,\n ZChatAiAttachment,\n ZChatAiConfig,\n ZChatAiSendEvent,\n ZChatAiPosition,\n} from './z-chat-ai.types';\nimport {\n zChatAiButtonVariants,\n zChatAiButtonWrapperVariants,\n zChatAiContainerVariants,\n zChatAiMessageVariants,\n zChatAiSuggestionVariants,\n zChatAiInputVariants,\n} from './z-chat-ai.variants';\n\n@Component({\n selector: 'z-chat-ai',\n imports: [ZIconComponent, TranslatePipe, FormsModule],\n standalone: true,\n templateUrl: './z-chat-ai.component.html',\n styleUrl: './z-chat-ai.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'z-chat-ai',\n },\n exportAs: 'zChatAi',\n})\nexport class ZChatAiComponent {\n public readonly class = input<ClassValue>('');\n public readonly zPosition = input<ZChatAiPosition>('bottom-right');\n public readonly zPulse = input<boolean>(true);\n public readonly zMessages = input<ZChatAiMessage[]>([]);\n public readonly zSuggestions = input<ZChatAiSuggestion[]>([]);\n public readonly zConfig = input<ZChatAiConfig>({});\n public readonly zTyping = input<boolean>(false);\n public readonly zOpen = model<boolean>(false);\n\n public readonly zOnSend = output<ZChatAiSendEvent>();\n public readonly zOnSuggestionClick = output<ZChatAiSuggestion>();\n public readonly zOnAttachmentRemove = output<ZChatAiAttachment>();\n\n protected readonly inputValue = signal('');\n protected readonly attachments = signal<ZChatAiAttachment[]>([]);\n protected readonly fileInputRef = viewChild<ElementRef<HTMLInputElement>>('fileInput');\n protected readonly messagesContainerRef = viewChild<ElementRef<HTMLDivElement>>('messagesContainer');\n\n protected readonly buttonWrapperClasses = computed(() =>\n zMergeClasses(\n zChatAiButtonWrapperVariants({\n zPosition: this.zPosition(),\n zPulse: this.zPulse(),\n })\n )\n );\n\n protected readonly buttonClasses = computed(() => zMergeClasses(zChatAiButtonVariants()));\n\n protected readonly containerClasses = computed(() =>\n zMergeClasses(\n zChatAiContainerVariants({\n zPosition: this.zPosition(),\n }),\n this.class()\n )\n );\n\n protected readonly inputClasses = computed(() => zMergeClasses(zChatAiInputVariants()));\n\n protected readonly config = computed(() => ({\n title: this.zConfig().title ?? 'AI Assistant',\n subtitle: this.zConfig().subtitle ?? 'How can I help you today?',\n placeholder: this.zConfig().placeholder ?? 'Type a message...',\n welcomeMessage: this.zConfig().welcomeMessage,\n avatarUrl: this.zConfig().avatarUrl,\n botName: this.zConfig().botName ?? 'Assistant',\n maxFileSize: this.zConfig().maxFileSize ?? 10 * 1024 * 1024,\n allowedFileTypes: this.zConfig().allowedFileTypes ?? ['image/*', '.pdf', '.doc', '.docx'],\n maxFiles: this.zConfig().maxFiles ?? 5,\n }));\n\n protected toggleOpen(): void {\n this.zOpen.update(v => !v);\n }\n\n protected close(): void {\n this.zOpen.set(false);\n }\n\n protected getMessageClasses(type: ZChatAiMessage['type']): string {\n return zChatAiMessageVariants({ zType: type });\n }\n\n protected getSuggestionClasses(color: ZChatAiSuggestion['color']): string {\n return zChatAiSuggestionVariants({ zColor: color ?? 'default' });\n }\n\n protected sendMessage(): void {\n const message = this.inputValue().trim();\n if (!message && this.attachments().length === 0) {\n return;\n }\n\n this.zOnSend.emit({\n message,\n attachments: [...this.attachments()],\n });\n\n this.inputValue.set('');\n this.attachments.set([]);\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n this.sendMessage();\n }\n }\n\n protected onSuggestionClick(suggestion: ZChatAiSuggestion): void {\n this.zOnSuggestionClick.emit(suggestion);\n }\n\n protected openFileDialog(): void {\n this.fileInputRef()?.nativeElement.click();\n }\n\n protected onFileSelect(event: Event): void {\n const input = event.target as HTMLInputElement;\n const { files } = input;\n if (!files) {\n return;\n }\n\n const config = this.config();\n const currentAttachments = this.attachments();\n\n if (currentAttachments.length + files.length > config.maxFiles) {\n return;\n }\n\n const newAttachments: ZChatAiAttachment[] = [];\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n if (file.size > config.maxFileSize) {\n continue;\n }\n\n newAttachments.push({\n id: crypto.randomUUID(),\n name: file.name,\n size: file.size,\n type: file.type,\n status: 'uploaded',\n });\n }\n\n this.attachments.update(att => [...att, ...newAttachments]);\n input.value = '';\n }\n\n protected removeAttachment(attachment: ZChatAiAttachment): void {\n this.attachments.update(att => att.filter(a => a.id !== attachment.id));\n this.zOnAttachmentRemove.emit(attachment);\n }\n\n protected formatFileSize(bytes: number): string {\n if (bytes < 1024) {\n return bytes + ' B';\n }\n if (bytes < 1024 * 1024) {\n return (bytes / 1024).toFixed(1) + ' KB';\n }\n return (bytes / (1024 * 1024)).toFixed(1) + ' MB';\n }\n\n protected scrollToBottom(): void {\n const container = this.messagesContainerRef()?.nativeElement;\n if (container) {\n container.scrollTop = container.scrollHeight;\n }\n }\n}\n","<div class=\"z-chat-ai-button-wrapper\" [class]=\"buttonWrapperClasses()\">\n <button\n type=\"button\"\n [class]=\"buttonClasses()\"\n (click)=\"toggleOpen()\"\n [attr.aria-expanded]=\"zOpen()\"\n aria-label=\"Toggle chat\">\n <z-icon\n [zType]=\"zOpen() ? 'lucideX' : 'lucideMessageCircle'\"\n zSize=\"24\"\n class=\"transition-transform duration-300\"\n [class.rotate-90]=\"zOpen()\" />\n </button>\n</div>\n\n@if (zOpen()) {\n <div [class]=\"containerClasses()\">\n <div class=\"z-chat-ai-header border-border bg-muted/30 flex items-center gap-3 border-b p-4\">\n @if (config().avatarUrl) {\n <img [src]=\"config().avatarUrl\" [alt]=\"config().botName\" class=\"size-10 rounded-full object-cover\" />\n } @else {\n <div class=\"bg-primary/10 flex size-10 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideBot\" zSize=\"20\" class=\"text-primary\" />\n </div>\n }\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"truncate text-sm font-semibold\">{{ config().title }}</h3>\n <p class=\"text-muted-foreground truncate text-xs\">{{ config().subtitle }}</p>\n </div>\n <button\n type=\"button\"\n class=\"hover:bg-muted flex size-8 cursor-pointer items-center justify-center rounded-full transition-colors\"\n (click)=\"close()\"\n aria-label=\"Close chat\">\n <z-icon zType=\"lucideX\" zSize=\"18\" />\n </button>\n </div>\n\n <div #messagesContainer class=\"z-chat-ai-body flex-1 space-y-3 overflow-y-auto p-4\">\n @if (config().welcomeMessage && zMessages().length === 0) {\n <div class=\"py-8 text-center\">\n <div class=\"bg-primary/10 mx-auto mb-4 flex size-16 items-center justify-center rounded-full\">\n <z-icon zType=\"lucideSparkles\" zSize=\"28\" class=\"text-primary\" />\n </div>\n <p class=\"text-muted-foreground text-sm\">{{ config().welcomeMessage }}</p>\n </div>\n }\n\n @for (message of zMessages(); track message.id) {\n <div [class]=\"getMessageClasses(message.type)\">\n <div class=\"whitespace-pre-wrap\">{{ message.content }}</div>\n @if (message.attachments?.length) {\n <div class=\"mt-2 flex flex-wrap gap-2\">\n @for (attachment of message.attachments; track attachment.id) {\n <div class=\"flex items-center gap-1.5 rounded bg-black/10 px-2 py-1 text-xs\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n </div>\n }\n </div>\n }\n </div>\n }\n\n @if (zTyping()) {\n <div class=\"z-chat-ai-typing bg-muted mr-auto flex items-center gap-1 rounded-2xl rounded-bl-md px-4 py-3\">\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n <span class=\"z-chat-ai-typing-dot\"></span>\n </div>\n }\n </div>\n\n @if (zSuggestions().length > 0 && zMessages().length === 0) {\n <div class=\"z-chat-ai-suggestions px-4 pb-2\">\n <div class=\"scrollbar-hide flex gap-2 overflow-x-auto pb-2\">\n @for (suggestion of zSuggestions(); track suggestion.id) {\n <button\n type=\"button\"\n [class]=\"getSuggestionClasses(suggestion.color)\"\n (click)=\"onSuggestionClick(suggestion)\">\n @if (suggestion.icon) {\n <z-icon [zType]=\"$any(suggestion.icon)\" zSize=\"14\" />\n }\n {{ suggestion.label }}\n </button>\n }\n </div>\n </div>\n }\n\n <div class=\"z-chat-ai-footer border-border border-t p-4\">\n @if (attachments().length > 0) {\n <div class=\"mb-3 flex flex-wrap gap-2\">\n @for (attachment of attachments(); track attachment.id) {\n <div class=\"bg-muted flex items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs\">\n <z-icon zType=\"lucideFile\" zSize=\"14\" />\n <span class=\"max-w-24 truncate\">{{ attachment.name }}</span>\n <span class=\"text-muted-foreground\">({{ formatFileSize(attachment.size) }})</span>\n <button\n type=\"button\"\n class=\"hover:bg-destructive/20 text-muted-foreground hover:text-destructive flex size-4 items-center justify-center rounded-full transition-colors\"\n (click)=\"removeAttachment(attachment)\">\n <z-icon zType=\"lucideX\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n }\n\n <div [class]=\"inputClasses()\">\n <input\n #fileInput\n type=\"file\"\n class=\"hidden\"\n [accept]=\"config().allowedFileTypes.join(',')\"\n multiple\n (change)=\"onFileSelect($event)\" />\n <button\n type=\"button\"\n class=\"hover:bg-muted text-muted-foreground hover:text-foreground flex size-8 shrink-0 items-center justify-center rounded-md transition-colors\"\n (click)=\"openFileDialog()\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_attach' | translate\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"18\" />\n </button>\n <input\n type=\"text\"\n class=\"placeholder:text-muted-foreground min-w-0 flex-1 bg-transparent text-sm outline-none\"\n [placeholder]=\"config().placeholder\"\n [(ngModel)]=\"inputValue\"\n (keydown)=\"onKeydown($event)\" />\n <button\n type=\"button\"\n class=\"bg-primary text-primary-foreground hover:bg-primary/90 flex size-8 shrink-0 items-center justify-center rounded-md transition-colors disabled:cursor-not-allowed disabled:opacity-50\"\n (click)=\"sendMessage()\"\n [disabled]=\"!inputValue().trim() && attachments().length === 0\"\n [attr.aria-label]=\"'i18n_z_ui_chat_ai_send' | translate\">\n <z-icon zType=\"lucideSend\" zSize=\"16\" />\n </button>\n </div>\n </div>\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;AAEO,MAAM,4BAA4B,GAAG,GAAG,CAAC,CAAC,0BAA0B,EAAE,gBAAgB,CAAC,EAAE;AAC9F,IAAA,QAAQ,EAAE;AACR,QAAA,SAAS,EAAE;AACT,YAAA,cAAc,EAAE,mBAAmB;AACnC,YAAA,aAAa,EAAE,kBAAkB;AACjC,YAAA,WAAW,EAAE,eAAe;AAC5B,YAAA,UAAU,EAAE,cAAc;AAC3B,SAAA;AACD,QAAA,MAAM,EAAE;AACN,YAAA,IAAI,EAAE,iCAAiC;AACvC,YAAA,KAAK,EAAE,EAAE;AACV,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,SAAS,EAAE,cAAc;AACzB,QAAA,MAAM,EAAE,IAAI;AACb,KAAA;AACF,CAAA;AAIM,MAAM,qBAAqB,GAAG,GAAG,CAAC;IACvC,kBAAkB;IAClB,+EAA+E;IAC/E,8CAA8C;IAC9C,sCAAsC;IACtC,iCAAiC;IACjC,uEAAuE;AACxE,CAAA;AAIM,MAAM,wBAAwB,GAAG,GAAG,CACzC;IACE,qBAAqB;IACrB,6CAA6C;IAC7C,2DAA2D;IAC3D,iBAAiB;IACjB,sCAAsC;CACvC,EACD;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,SAAS,EAAE;AACT,YAAA,cAAc,EAAE,mBAAmB;AACnC,YAAA,aAAa,EAAE,kBAAkB;AACjC,YAAA,WAAW,EAAE,gBAAgB;AAC7B,YAAA,UAAU,EAAE,eAAe;AAC5B,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,SAAS,EAAE,cAAc;AAC1B,KAAA;AACF,CAAA;AAKI,MAAM,sBAAsB,GAAG,GAAG,CACvC;IACE,mBAAmB;IACnB,uCAAuC;IACvC,yBAAyB;IACzB,0DAA0D;CAC3D,EACD;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,KAAK,EAAE;AACL,YAAA,IAAI,EAAE,CAAC,SAAS,EAAE,oCAAoC,EAAE,eAAe,CAAC;AACxE,YAAA,GAAG,EAAE,CAAC,SAAS,EAAE,0BAA0B,EAAE,eAAe,CAAC;AAC7D,YAAA,MAAM,EAAE,CAAC,SAAS,EAAE,mCAAmC,EAAE,qBAAqB,CAAC;AAChF,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,KAAK,EAAE,KAAK;AACb,KAAA;AACF,CAAA;AAKI,MAAM,yBAAyB,GAAG,GAAG,CAC1C;IACE,sBAAsB;IACtB,2DAA2D;IAC3D,sDAAsD;IACtD,oCAAoC;IACpC,iCAAiC;CAClC,EACD;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,MAAM,EAAE;AACN,YAAA,OAAO,EAAE,iFAAiF;AAC1F,YAAA,IAAI,EAAE,yHAAyH;AAC/H,YAAA,KAAK,EACH,gIAAgI;AAClI,YAAA,MAAM,EACJ,uIAAuI;AACzI,YAAA,MAAM,EACJ,uIAAuI;AACzI,YAAA,IAAI,EAAE,yHAAyH;AAC/H,YAAA,IAAI,EAAE,yHAAyH;AAC/H,YAAA,MAAM,EACJ,uIAAuI;AAC1I,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,MAAM,EAAE,SAAS;AAClB,KAAA;AACF,CAAA;AAKI,MAAM,oBAAoB,GAAG,GAAG,CAAC;IACtC,iGAAiG;IACjG,oEAAoE;IACpE,oCAAoC;IACpC,4EAA4E;AAC7E,CAAA;;MCzEY,gBAAgB,CAAA;AACX,IAAA,KAAK,GAAG,KAAK,CAAa,EAAE,iDAAC;AAC7B,IAAA,SAAS,GAAG,KAAK,CAAkB,cAAc,qDAAC;AAClD,IAAA,MAAM,GAAG,KAAK,CAAU,IAAI,kDAAC;AAC7B,IAAA,SAAS,GAAG,KAAK,CAAmB,EAAE,qDAAC;AACvC,IAAA,YAAY,GAAG,KAAK,CAAsB,EAAE,wDAAC;AAC7C,IAAA,OAAO,GAAG,KAAK,CAAgB,EAAE,mDAAC;AAClC,IAAA,OAAO,GAAG,KAAK,CAAU,KAAK,mDAAC;AAC/B,IAAA,KAAK,GAAG,KAAK,CAAU,KAAK,iDAAC;IAE7B,OAAO,GAAG,MAAM,EAAoB;IACpC,kBAAkB,GAAG,MAAM,EAAqB;IAChD,mBAAmB,GAAG,MAAM,EAAqB;AAE9C,IAAA,UAAU,GAAG,MAAM,CAAC,EAAE,sDAAC;AACvB,IAAA,WAAW,GAAG,MAAM,CAAsB,EAAE,uDAAC;AAC7C,IAAA,YAAY,GAAG,SAAS,CAA+B,WAAW,wDAAC;AACnE,IAAA,oBAAoB,GAAG,SAAS,CAA6B,mBAAmB,gEAAC;IAEjF,oBAAoB,GAAG,QAAQ,CAAC,MACjD,aAAa,CACX,4BAA4B,CAAC;AAC3B,QAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;AAC3B,QAAA,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;KACtB,CAAC,CACH,gEACF;AAEkB,IAAA,aAAa,GAAG,QAAQ,CAAC,MAAM,aAAa,CAAC,qBAAqB,EAAE,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,eAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;IAEtE,gBAAgB,GAAG,QAAQ,CAAC,MAC7C,aAAa,CACX,wBAAwB,CAAC;AACvB,QAAA,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;AAC5B,KAAA,CAAC,EACF,IAAI,CAAC,KAAK,EAAE,CACb,4DACF;AAEkB,IAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,aAAa,CAAC,oBAAoB,EAAE,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,cAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAAC;AAEpE,IAAA,MAAM,GAAG,QAAQ,CAAC,OAAO;QAC1C,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,cAAc;QAC7C,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,IAAI,2BAA2B;QAChE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,IAAI,mBAAmB;AAC9D,QAAA,cAAc,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,cAAc;AAC7C,QAAA,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS;QACnC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,IAAI,WAAW;AAC9C,QAAA,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI;AAC3D,QAAA,gBAAgB,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,gBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;QACzF,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,IAAI,CAAC;AACvC,KAAA,CAAC,kDAAC;IAEO,UAAU,GAAA;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B;IAEU,KAAK,GAAA;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;IACvB;AAEU,IAAA,iBAAiB,CAAC,IAA4B,EAAA;QACtD,OAAO,sBAAsB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAChD;AAEU,IAAA,oBAAoB,CAAC,KAAiC,EAAA;QAC9D,OAAO,yBAAyB,CAAC,EAAE,MAAM,EAAE,KAAK,IAAI,SAAS,EAAE,CAAC;IAClE;IAEU,WAAW,GAAA;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE;AACxC,QAAA,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;YAC/C;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAChB,OAAO;AACP,YAAA,WAAW,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;AACrC,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1B;AAEU,IAAA,SAAS,CAAC,KAAoB,EAAA;QACtC,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE;YAC5C,KAAK,CAAC,cAAc,EAAE;YACtB,IAAI,CAAC,WAAW,EAAE;QACpB;IACF;AAEU,IAAA,iBAAiB,CAAC,UAA6B,EAAA;AACvD,QAAA,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;IAC1C;IAEU,cAAc,GAAA;QACtB,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE;IAC5C;AAEU,IAAA,YAAY,CAAC,KAAY,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;AAC9C,QAAA,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK;QACvB,IAAI,CAAC,KAAK,EAAE;YACV;QACF;AAEA,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;AAC5B,QAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,WAAW,EAAE;AAE7C,QAAA,IAAI,kBAAkB,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE;YAC9D;QACF;QAEA,MAAM,cAAc,GAAwB,EAAE;AAC9C,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AACrC,YAAA,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC;YACrB,IAAI,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE;gBAClC;YACF;YAEA,cAAc,CAAC,IAAI,CAAC;AAClB,gBAAA,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE;gBACvB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;AACf,gBAAA,MAAM,EAAE,UAAU;AACnB,aAAA,CAAC;QACJ;AAEA,QAAA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,cAAc,CAAC,CAAC;AAC3D,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEU,IAAA,gBAAgB,CAAC,UAA6B,EAAA;QACtD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC,CAAC;AACvE,QAAA,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC;IAC3C;AAEU,IAAA,cAAc,CAAC,KAAa,EAAA;AACpC,QAAA,IAAI,KAAK,GAAG,IAAI,EAAE;YAChB,OAAO,KAAK,GAAG,IAAI;QACrB;AACA,QAAA,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,EAAE;AACvB,YAAA,OAAO,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK;QAC1C;AACA,QAAA,OAAO,CAAC,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK;IACnD;IAEU,cAAc,GAAA;QACtB,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,EAAE,aAAa;QAC5D,IAAI,SAAS,EAAE;AACb,YAAA,SAAS,CAAC,SAAS,GAAG,SAAS,CAAC,YAAY;QAC9C;IACF;uGAzJW,gBAAgB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAhB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,gBAAgB,+gDC/C7B,2mMA+IA,EAAA,MAAA,EAAA,CAAA,s3FAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,ED3GY,cAAc,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,OAAA,EAAA,cAAA,EAAA,MAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAiB,WAAW,0mBAA1B,aAAa,EAAA,IAAA,EAAA,WAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAW5B,gBAAgB,EAAA,UAAA,EAAA,CAAA;kBAb5B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,WACZ,CAAC,cAAc,EAAE,aAAa,EAAE,WAAW,CAAC,EAAA,UAAA,EACzC,IAAI,EAAA,eAAA,EAGC,uBAAuB,CAAC,MAAM,iBAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,WAAW;AACnB,qBAAA,EAAA,QAAA,EACS,SAAS,EAAA,QAAA,EAAA,2mMAAA,EAAA,MAAA,EAAA,CAAA,s3FAAA,CAAA,EAAA;AAkBuD,SAAA,CAAA,EAAA,cAAA,EAAA,EAAA,KAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,WAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,QAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,WAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,cAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,KAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,OAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,aAAA,CAAA,EAAA,CAAA,EAAA,OAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,kBAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,CAAA,EAAA,mBAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,MAAA,EAAA,IAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,IAAA,EAAA,CAAA,WAAW,8EACL,mBAAmB,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AEhErG;;AAEG;;;;"}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { ElementRef } from '@angular/core';
|
|
3
|
-
import { ClassValue } from 'clsx';
|
|
4
|
-
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
|
-
import { VariantProps } from 'class-variance-authority';
|
|
6
|
-
|
|
7
|
-
type ZChatAiPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
8
|
-
type ZChatAiMessageType = 'user' | 'bot' | 'system';
|
|
9
|
-
type ZChatAiSuggestionColor = 'default' | 'blue' | 'green' | 'purple' | 'orange' | 'pink' | 'cyan' | 'yellow';
|
|
10
|
-
interface ZChatAiAttachment {
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
size: number;
|
|
14
|
-
type: string;
|
|
15
|
-
url?: string;
|
|
16
|
-
progress?: number;
|
|
17
|
-
status?: 'uploading' | 'uploaded' | 'error';
|
|
18
|
-
}
|
|
19
|
-
interface ZChatAiMessage {
|
|
20
|
-
id: string;
|
|
21
|
-
type: ZChatAiMessageType;
|
|
22
|
-
content: string;
|
|
23
|
-
timestamp: Date;
|
|
24
|
-
attachments?: ZChatAiAttachment[];
|
|
25
|
-
isTyping?: boolean;
|
|
26
|
-
}
|
|
27
|
-
interface ZChatAiSuggestion {
|
|
28
|
-
id: string;
|
|
29
|
-
label: string;
|
|
30
|
-
value: string;
|
|
31
|
-
color?: ZChatAiSuggestionColor;
|
|
32
|
-
icon?: string;
|
|
33
|
-
}
|
|
34
|
-
interface ZChatAiConfig {
|
|
35
|
-
title?: string;
|
|
36
|
-
subtitle?: string;
|
|
37
|
-
placeholder?: string;
|
|
38
|
-
welcomeMessage?: string;
|
|
39
|
-
avatarUrl?: string;
|
|
40
|
-
botName?: string;
|
|
41
|
-
maxFileSize?: number;
|
|
42
|
-
allowedFileTypes?: string[];
|
|
43
|
-
maxFiles?: number;
|
|
44
|
-
}
|
|
45
|
-
interface ZChatAiSendEvent {
|
|
46
|
-
message: string;
|
|
47
|
-
attachments: ZChatAiAttachment[];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
declare class ZChatAiComponent {
|
|
51
|
-
readonly class: _angular_core.InputSignal<ClassValue>;
|
|
52
|
-
readonly zPosition: _angular_core.InputSignal<ZChatAiPosition>;
|
|
53
|
-
readonly zPulse: _angular_core.InputSignal<boolean>;
|
|
54
|
-
readonly zMessages: _angular_core.InputSignal<ZChatAiMessage[]>;
|
|
55
|
-
readonly zSuggestions: _angular_core.InputSignal<ZChatAiSuggestion[]>;
|
|
56
|
-
readonly zConfig: _angular_core.InputSignal<ZChatAiConfig>;
|
|
57
|
-
readonly zTyping: _angular_core.InputSignal<boolean>;
|
|
58
|
-
readonly zOpen: _angular_core.ModelSignal<boolean>;
|
|
59
|
-
readonly zOnSend: _angular_core.OutputEmitterRef<ZChatAiSendEvent>;
|
|
60
|
-
readonly zOnSuggestionClick: _angular_core.OutputEmitterRef<ZChatAiSuggestion>;
|
|
61
|
-
readonly zOnAttachmentRemove: _angular_core.OutputEmitterRef<ZChatAiAttachment>;
|
|
62
|
-
protected readonly inputValue: _angular_core.WritableSignal<string>;
|
|
63
|
-
protected readonly attachments: _angular_core.WritableSignal<ZChatAiAttachment[]>;
|
|
64
|
-
protected readonly fileInputRef: _angular_core.Signal<ElementRef<HTMLInputElement> | undefined>;
|
|
65
|
-
protected readonly messagesContainerRef: _angular_core.Signal<ElementRef<HTMLDivElement> | undefined>;
|
|
66
|
-
protected readonly buttonWrapperClasses: _angular_core.Signal<string>;
|
|
67
|
-
protected readonly buttonClasses: _angular_core.Signal<string>;
|
|
68
|
-
protected readonly containerClasses: _angular_core.Signal<string>;
|
|
69
|
-
protected readonly inputClasses: _angular_core.Signal<string>;
|
|
70
|
-
protected readonly config: _angular_core.Signal<{
|
|
71
|
-
title: string;
|
|
72
|
-
subtitle: string;
|
|
73
|
-
placeholder: string;
|
|
74
|
-
welcomeMessage: string | undefined;
|
|
75
|
-
avatarUrl: string | undefined;
|
|
76
|
-
botName: string;
|
|
77
|
-
maxFileSize: number;
|
|
78
|
-
allowedFileTypes: string[];
|
|
79
|
-
maxFiles: number;
|
|
80
|
-
}>;
|
|
81
|
-
protected toggleOpen(): void;
|
|
82
|
-
protected close(): void;
|
|
83
|
-
protected getMessageClasses(type: ZChatAiMessage['type']): string;
|
|
84
|
-
protected getSuggestionClasses(color: ZChatAiSuggestion['color']): string;
|
|
85
|
-
protected sendMessage(): void;
|
|
86
|
-
protected onKeydown(event: KeyboardEvent): void;
|
|
87
|
-
protected onSuggestionClick(suggestion: ZChatAiSuggestion): void;
|
|
88
|
-
protected openFileDialog(): void;
|
|
89
|
-
protected onFileSelect(event: Event): void;
|
|
90
|
-
protected removeAttachment(attachment: ZChatAiAttachment): void;
|
|
91
|
-
protected formatFileSize(bytes: number): string;
|
|
92
|
-
protected scrollToBottom(): void;
|
|
93
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ZChatAiComponent, never>;
|
|
94
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ZChatAiComponent, "z-chat-ai", ["zChatAi"], { "class": { "alias": "class"; "required": false; "isSignal": true; }; "zPosition": { "alias": "zPosition"; "required": false; "isSignal": true; }; "zPulse": { "alias": "zPulse"; "required": false; "isSignal": true; }; "zMessages": { "alias": "zMessages"; "required": false; "isSignal": true; }; "zSuggestions": { "alias": "zSuggestions"; "required": false; "isSignal": true; }; "zConfig": { "alias": "zConfig"; "required": false; "isSignal": true; }; "zTyping": { "alias": "zTyping"; "required": false; "isSignal": true; }; "zOpen": { "alias": "zOpen"; "required": false; "isSignal": true; }; }, { "zOpen": "zOpenChange"; "zOnSend": "zOnSend"; "zOnSuggestionClick": "zOnSuggestionClick"; "zOnAttachmentRemove": "zOnAttachmentRemove"; }, never, never, true, never>;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
declare const zChatAiButtonWrapperVariants: (props?: ({
|
|
98
|
-
zPosition?: "bottom-right" | "bottom-left" | "top-right" | "top-left" | null | undefined;
|
|
99
|
-
zPulse?: boolean | null | undefined;
|
|
100
|
-
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
101
|
-
type ZChatAiButtonWrapperVariants = VariantProps<typeof zChatAiButtonWrapperVariants>;
|
|
102
|
-
declare const zChatAiButtonVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
103
|
-
type ZChatAiButtonVariants = VariantProps<typeof zChatAiButtonVariants>;
|
|
104
|
-
declare const zChatAiContainerVariants: (props?: ({
|
|
105
|
-
zPosition?: "bottom-right" | "bottom-left" | "top-right" | "top-left" | null | undefined;
|
|
106
|
-
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
107
|
-
type ZChatAiContainerVariants = VariantProps<typeof zChatAiContainerVariants>;
|
|
108
|
-
declare const zChatAiMessageVariants: (props?: ({
|
|
109
|
-
zType?: "user" | "bot" | "system" | null | undefined;
|
|
110
|
-
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
111
|
-
type ZChatAiMessageVariants = VariantProps<typeof zChatAiMessageVariants>;
|
|
112
|
-
declare const zChatAiSuggestionVariants: (props?: ({
|
|
113
|
-
zColor?: "default" | "blue" | "green" | "purple" | "orange" | "pink" | "cyan" | "yellow" | null | undefined;
|
|
114
|
-
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
115
|
-
type ZChatAiSuggestionVariants = VariantProps<typeof zChatAiSuggestionVariants>;
|
|
116
|
-
declare const zChatAiInputVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
117
|
-
type ZChatAiInputVariants = VariantProps<typeof zChatAiInputVariants>;
|
|
118
|
-
|
|
119
|
-
export { ZChatAiComponent, zChatAiButtonVariants, zChatAiButtonWrapperVariants, zChatAiContainerVariants, zChatAiInputVariants, zChatAiMessageVariants, zChatAiSuggestionVariants };
|
|
120
|
-
export type { ZChatAiAttachment, ZChatAiButtonVariants, ZChatAiButtonWrapperVariants, ZChatAiConfig, ZChatAiContainerVariants, ZChatAiInputVariants, ZChatAiMessage, ZChatAiMessageType, ZChatAiMessageVariants, ZChatAiPosition, ZChatAiSendEvent, ZChatAiSuggestion, ZChatAiSuggestionColor, ZChatAiSuggestionVariants };
|