@shival99/z-ui 1.3.37 → 1.3.38
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/fesm2022/shival99-z-ui-components-z-chat-ai.mjs +236 -0
- package/fesm2022/shival99-z-ui-components-z-chat-ai.mjs.map +1 -0
- package/fesm2022/shival99-z-ui-components-z-steps.mjs +57 -2
- package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-tags.mjs +6 -5
- package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-i18n.mjs +18 -0
- package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -1
- package/package.json +5 -1
- package/types/shival99-z-ui-components-z-chat-ai.d.ts +120 -0
- package/types/shival99-z-ui-components-z-steps.d.ts +3 -1
- package/types/shival99-z-ui-components-z-tags.d.ts +2 -1
|
@@ -0,0 +1,236 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":"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"}
|
|
@@ -104,6 +104,43 @@ const zStepsArrowItemVariants = cva(['z-steps-arrow-item relative flex flex-1 fl
|
|
|
104
104
|
status: 'pending',
|
|
105
105
|
},
|
|
106
106
|
});
|
|
107
|
+
const zStepsDotVariants = cva(['rounded-full transition-all duration-200'], {
|
|
108
|
+
variants: {
|
|
109
|
+
size: {
|
|
110
|
+
sm: 'w-2 h-2',
|
|
111
|
+
default: 'w-2.5 h-2.5',
|
|
112
|
+
lg: 'w-3 h-3',
|
|
113
|
+
},
|
|
114
|
+
status: {
|
|
115
|
+
pending: 'bg-muted-foreground/30',
|
|
116
|
+
current: 'bg-primary ring-4 ring-primary/20',
|
|
117
|
+
completed: 'bg-primary ring-4 ring-primary/20',
|
|
118
|
+
error: 'bg-destructive ring-4 ring-destructive/20',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
defaultVariants: {
|
|
122
|
+
size: 'default',
|
|
123
|
+
status: 'pending',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const zStepsDotLineVariants = cva(['transition-colors duration-200'], {
|
|
127
|
+
variants: {
|
|
128
|
+
orientation: {
|
|
129
|
+
vertical: 'w-px flex-1 min-h-14',
|
|
130
|
+
horizontal: 'h-px flex-1',
|
|
131
|
+
},
|
|
132
|
+
status: {
|
|
133
|
+
pending: 'bg-muted-foreground/20',
|
|
134
|
+
current: 'bg-muted-foreground/20',
|
|
135
|
+
completed: 'bg-primary',
|
|
136
|
+
error: 'bg-destructive/30',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
defaultVariants: {
|
|
140
|
+
orientation: 'horizontal',
|
|
141
|
+
status: 'pending',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
107
144
|
|
|
108
145
|
const RESPONSIVE_BREAKPOINT = 640;
|
|
109
146
|
class ZStepsComponent {
|
|
@@ -190,6 +227,24 @@ class ZStepsComponent {
|
|
|
190
227
|
return zMergeClasses(baseClasses, positionClass);
|
|
191
228
|
});
|
|
192
229
|
}, ...(ngDevMode ? [{ debugName: "getArrowClassesByIndex" }] : []));
|
|
230
|
+
getDotClassesByIndex = computed(() => {
|
|
231
|
+
const size = this.zSize();
|
|
232
|
+
const steps = this.mergedSteps();
|
|
233
|
+
const current = this.currentStep();
|
|
234
|
+
return steps.map((step, index) => {
|
|
235
|
+
const status = this._getStepStatus(step, index, current);
|
|
236
|
+
return zStepsDotVariants({ size, status });
|
|
237
|
+
});
|
|
238
|
+
}, ...(ngDevMode ? [{ debugName: "getDotClassesByIndex" }] : []));
|
|
239
|
+
getDotLineClassesByIndex = computed(() => {
|
|
240
|
+
const orientation = this.effectiveOrientation();
|
|
241
|
+
const steps = this.mergedSteps();
|
|
242
|
+
const current = this.currentStep();
|
|
243
|
+
return steps.map((step, index) => {
|
|
244
|
+
const status = this._getConnectorStatus(step, index, current);
|
|
245
|
+
return zStepsDotLineVariants({ orientation, status });
|
|
246
|
+
});
|
|
247
|
+
}, ...(ngDevMode ? [{ debugName: "getDotLineClassesByIndex" }] : []));
|
|
193
248
|
defaultIconSize = computed(() => {
|
|
194
249
|
const size = this.zSize();
|
|
195
250
|
if (size === 'sm') {
|
|
@@ -322,13 +377,13 @@ class ZStepsComponent {
|
|
|
322
377
|
this.zOnStepClick.emit(index);
|
|
323
378
|
}
|
|
324
379
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZStepsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
325
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZStepsComponent, isStandalone: true, selector: "z-steps", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zSteps: { classPropertyName: "zSteps", publicName: "zSteps", isSignal: true, isRequired: true, transformFunction: null }, zCurrent: { classPropertyName: "zCurrent", publicName: "zCurrent", isSignal: true, isRequired: false, transformFunction: null }, zOrientation: { classPropertyName: "zOrientation", publicName: "zOrientation", isSignal: true, isRequired: false, transformFunction: null }, zType: { classPropertyName: "zType", publicName: "zType", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zClickable: { classPropertyName: "zClickable", publicName: "zClickable", isSignal: true, isRequired: false, transformFunction: null }, zShowNumber: { classPropertyName: "zShowNumber", publicName: "zShowNumber", isSignal: true, isRequired: false, transformFunction: null }, zResponsive: { classPropertyName: "zResponsive", publicName: "zResponsive", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnStepClick: "zOnStepClick", zControl: "zControl" }, host: { classAttribute: "block" }, ngImport: i0, template: "<ol [class]=\"containerClasses()\">\n @for (step of mergedSteps(); track $index; let i = $index; let last = $last) {\n @if (effectiveOrientation() === 'vertical') {\n <!-- Vertical Layout -->\n <li\n [class]=\"getItemClasses()\"\n [class.!items-start]=\"!step.description && (step.title || step.icon)\"\n [class.items-center]=\"!step.description && (step.title || step.icon)\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"lineClasses()\"></div>\n }\n\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content -->\n @if (step.title || step.description) {\n <div class=\"flex min-w-0 flex-col\" [style.padding-top.px]=\"!step.description ? iconWidth() / 5 : 0\">\n @if (step.title) {\n <h3 class=\"leading-tight font-medium\">{{ step.title }}</h3>\n }\n @if (step.description) {\n <p class=\"text-muted-foreground mt-1 text-sm\">{{ step.description }}</p>\n }\n </div>\n }\n </li>\n } @else {\n <!-- Horizontal Layout -->\n <li\n [class]=\"zType() === 'arrow' ? 'flex-1' : 'flex-1 last:flex-none'\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n @if (zType() === 'arrow') {\n <!-- Arrow Style -->\n <div [class]=\"getArrowClassesByIndex()[i]\">\n <div class=\"flex items-center gap-3.5\">\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" class=\"shrink-0\" />\n }\n <div class=\"flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-semibold whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"mt-1 truncate text-xs whitespace-nowrap opacity-80\">\n {{ step.description }}\n </p>\n }\n </div>\n </div>\n </div>\n } @else if (zType() === 'inline') {\n <!-- Inline: Icon + Content + Line in one row -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content Inline -->\n @if (step.title || step.description) {\n <div class=\"ms-3 flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"max-w-30 truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 max-w-30 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n } @else {\n <!-- Default: Icon + Line row, Content below -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n\n <!-- Content Below -->\n @if (step.title || step.description) {\n <div\n class=\"z-steps-content mt-3 flex flex-col text-center\"\n [style.width.px]=\"150\"\n [style.margin-left.px]=\"(iconWidth() - 150) / 2\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n }\n </li>\n }\n }\n</ol>\n", styles: ["z-steps ol li:not(:last-child)>div[class*=border-s]{height:calc(100% + 2rem)}z-steps ol li[class*=mb-6]:not(:last-child)>div[class*=border-s]{height:calc(100% + 1.5rem)}z-steps ol li[class*=mb-10]:not(:last-child)>div[class*=border-s]{height:calc(100% + 2.5rem)}z-steps .z-steps-arrow-item{position:relative;display:flex;flex-direction:column;justify-content:center;transition:all .2s ease-out}z-steps .z-steps-arrow-item:hover{filter:brightness(.92)}z-steps .z-steps-arrow-first{border-radius:6px 0 0 6px;clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%)}z-steps .z-steps-arrow-middle{margin-left:-8px;padding-left:calc(16px + 1rem);clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%,16px 50%)}z-steps .z-steps-arrow-last{margin-left:-8px;padding-left:calc(16px + 1rem);border-radius:0 6px 6px 0;clip-path:polygon(0 0,100% 0,100% 100%,0 100%,16px 50%)}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
380
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZStepsComponent, isStandalone: true, selector: "z-steps", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zSteps: { classPropertyName: "zSteps", publicName: "zSteps", isSignal: true, isRequired: true, transformFunction: null }, zCurrent: { classPropertyName: "zCurrent", publicName: "zCurrent", isSignal: true, isRequired: false, transformFunction: null }, zOrientation: { classPropertyName: "zOrientation", publicName: "zOrientation", isSignal: true, isRequired: false, transformFunction: null }, zType: { classPropertyName: "zType", publicName: "zType", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zClickable: { classPropertyName: "zClickable", publicName: "zClickable", isSignal: true, isRequired: false, transformFunction: null }, zShowNumber: { classPropertyName: "zShowNumber", publicName: "zShowNumber", isSignal: true, isRequired: false, transformFunction: null }, zResponsive: { classPropertyName: "zResponsive", publicName: "zResponsive", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zOnStepClick: "zOnStepClick", zControl: "zControl" }, host: { classAttribute: "block" }, ngImport: i0, template: "<ol [class]=\"containerClasses()\">\n @for (step of mergedSteps(); track $index; let i = $index; let last = $last) {\n @if (effectiveOrientation() === 'vertical') {\n @if (zType() === 'dot') {\n <!-- Vertical Dot Layout -->\n <li\n class=\"flex items-start gap-3\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Dot + Line Column -->\n <div class=\"flex flex-col items-center\">\n <!-- Dot -->\n <span [class]=\"getDotClassesByIndex()[i]\" class=\"shrink-0\"></span>\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"getDotLineClassesByIndex()[i]\" class=\"my-1.5\"></div>\n }\n </div>\n\n <!-- Content (optional) -->\n @if (step.title) {\n <span\n class=\"pt-0.5 text-sm\"\n [class.text-foreground]=\"stepStatuses()[i] === 'current'\"\n [class.font-medium]=\"stepStatuses()[i] === 'current'\"\n [class.text-muted-foreground]=\"stepStatuses()[i] !== 'current'\">\n {{ step.title }}\n </span>\n }\n </li>\n } @else {\n <!-- Vertical Layout -->\n <li\n [class]=\"getItemClasses()\"\n [class.!items-start]=\"!step.description && (step.title || step.icon)\"\n [class.items-center]=\"!step.description && (step.title || step.icon)\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"lineClasses()\"></div>\n }\n\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content -->\n @if (step.title || step.description) {\n <div class=\"flex min-w-0 flex-col\" [style.padding-top.px]=\"!step.description ? iconWidth() / 5 : 0\">\n @if (step.title) {\n <h3 class=\"leading-tight font-medium\">{{ step.title }}</h3>\n }\n @if (step.description) {\n <p class=\"text-muted-foreground mt-1 text-sm\">{{ step.description }}</p>\n }\n </div>\n }\n </li>\n }\n } @else {\n <!-- Horizontal Layout -->\n <li\n [class]=\"zType() === 'arrow' ? 'flex-1' : 'flex-1 last:flex-none'\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n @if (zType() === 'arrow') {\n <!-- Arrow Style -->\n <div [class]=\"getArrowClassesByIndex()[i]\">\n <div class=\"flex items-center gap-3.5\">\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" class=\"shrink-0\" />\n }\n <div class=\"flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-semibold whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"mt-1 truncate text-xs whitespace-nowrap opacity-80\">\n {{ step.description }}\n </p>\n }\n </div>\n </div>\n </div>\n } @else if (zType() === 'dot') {\n <!-- Dot Style: Simple dots with optional labels -->\n <div class=\"flex items-center\">\n <!-- Dot -->\n <span [class]=\"getDotClassesByIndex()[i]\"></span>\n\n <!-- Content (optional) -->\n @if (step.title) {\n <span\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"ms-2 max-w-20 truncate text-sm whitespace-nowrap\"\n [class.text-foreground]=\"stepStatuses()[i] === 'current'\"\n [class.text-muted-foreground]=\"stepStatuses()[i] !== 'current'\">\n {{ step.title }}\n </span>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getDotLineClassesByIndex()[i]\" class=\"mx-2 min-w-8\"></div>\n }\n </div>\n } @else if (zType() === 'inline') {\n <!-- Inline: Icon + Content + Line in one row -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content Inline -->\n @if (step.title || step.description) {\n <div class=\"ms-3 flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"max-w-30 truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 max-w-30 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n } @else {\n <!-- Default: Icon + Line row, Content below -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n\n <!-- Content Below -->\n @if (step.title || step.description) {\n <div\n class=\"z-steps-content mt-3 flex flex-col text-center\"\n [style.width.px]=\"150\"\n [style.margin-left.px]=\"(iconWidth() - 150) / 2\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n }\n </li>\n }\n }\n</ol>\n", styles: ["z-steps ol li:not(:last-child)>div[class*=border-s]{height:calc(100% + 2rem)}z-steps ol li[class*=mb-6]:not(:last-child)>div[class*=border-s]{height:calc(100% + 1.5rem)}z-steps ol li[class*=mb-10]:not(:last-child)>div[class*=border-s]{height:calc(100% + 2.5rem)}z-steps .z-steps-arrow-item{position:relative;display:flex;flex-direction:column;justify-content:center;transition:all .2s ease-out}z-steps .z-steps-arrow-item:hover{filter:brightness(.92)}z-steps .z-steps-arrow-first{border-radius:6px 0 0 6px;clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%)}z-steps .z-steps-arrow-middle{margin-left:-8px;padding-left:calc(16px + 1rem);clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%,16px 50%)}z-steps .z-steps-arrow-last{margin-left:-8px;padding-left:calc(16px + 1rem);border-radius:0 6px 6px 0;clip-path:polygon(0 0,100% 0,100% 100%,0 100%,16px 50%)}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
326
381
|
}
|
|
327
382
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZStepsComponent, decorators: [{
|
|
328
383
|
type: Component,
|
|
329
384
|
args: [{ selector: 'z-steps', imports: [ZIconComponent, ZTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
330
385
|
class: 'block',
|
|
331
|
-
}, template: "<ol [class]=\"containerClasses()\">\n @for (step of mergedSteps(); track $index; let i = $index; let last = $last) {\n @if (effectiveOrientation() === 'vertical') {\n <!-- Vertical Layout -->\n <li\n [class]=\"getItemClasses()\"\n [class.!items-start]=\"!step.description && (step.title || step.icon)\"\n [class.items-center]=\"!step.description && (step.title || step.icon)\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"lineClasses()\"></div>\n }\n\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content -->\n @if (step.title || step.description) {\n <div class=\"flex min-w-0 flex-col\" [style.padding-top.px]=\"!step.description ? iconWidth() / 5 : 0\">\n @if (step.title) {\n <h3 class=\"leading-tight font-medium\">{{ step.title }}</h3>\n }\n @if (step.description) {\n <p class=\"text-muted-foreground mt-1 text-sm\">{{ step.description }}</p>\n }\n </div>\n }\n </li>\n } @else {\n <!-- Horizontal Layout -->\n <li\n [class]=\"zType() === 'arrow' ? 'flex-1' : 'flex-1 last:flex-none'\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n @if (zType() === 'arrow') {\n <!-- Arrow Style -->\n <div [class]=\"getArrowClassesByIndex()[i]\">\n <div class=\"flex items-center gap-3.5\">\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" class=\"shrink-0\" />\n }\n <div class=\"flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-semibold whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"mt-1 truncate text-xs whitespace-nowrap opacity-80\">\n {{ step.description }}\n </p>\n }\n </div>\n </div>\n </div>\n } @else if (zType() === 'inline') {\n <!-- Inline: Icon + Content + Line in one row -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content Inline -->\n @if (step.title || step.description) {\n <div class=\"ms-3 flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"max-w-30 truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 max-w-30 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n } @else {\n <!-- Default: Icon + Line row, Content below -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n\n <!-- Content Below -->\n @if (step.title || step.description) {\n <div\n class=\"z-steps-content mt-3 flex flex-col text-center\"\n [style.width.px]=\"150\"\n [style.margin-left.px]=\"(iconWidth() - 150) / 2\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n }\n </li>\n }\n }\n</ol>\n", styles: ["z-steps ol li:not(:last-child)>div[class*=border-s]{height:calc(100% + 2rem)}z-steps ol li[class*=mb-6]:not(:last-child)>div[class*=border-s]{height:calc(100% + 1.5rem)}z-steps ol li[class*=mb-10]:not(:last-child)>div[class*=border-s]{height:calc(100% + 2.5rem)}z-steps .z-steps-arrow-item{position:relative;display:flex;flex-direction:column;justify-content:center;transition:all .2s ease-out}z-steps .z-steps-arrow-item:hover{filter:brightness(.92)}z-steps .z-steps-arrow-first{border-radius:6px 0 0 6px;clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%)}z-steps .z-steps-arrow-middle{margin-left:-8px;padding-left:calc(16px + 1rem);clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%,16px 50%)}z-steps .z-steps-arrow-last{margin-left:-8px;padding-left:calc(16px + 1rem);border-radius:0 6px 6px 0;clip-path:polygon(0 0,100% 0,100% 100%,0 100%,16px 50%)}\n"] }]
|
|
386
|
+
}, template: "<ol [class]=\"containerClasses()\">\n @for (step of mergedSteps(); track $index; let i = $index; let last = $last) {\n @if (effectiveOrientation() === 'vertical') {\n @if (zType() === 'dot') {\n <!-- Vertical Dot Layout -->\n <li\n class=\"flex items-start gap-3\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Dot + Line Column -->\n <div class=\"flex flex-col items-center\">\n <!-- Dot -->\n <span [class]=\"getDotClassesByIndex()[i]\" class=\"shrink-0\"></span>\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"getDotLineClassesByIndex()[i]\" class=\"my-1.5\"></div>\n }\n </div>\n\n <!-- Content (optional) -->\n @if (step.title) {\n <span\n class=\"pt-0.5 text-sm\"\n [class.text-foreground]=\"stepStatuses()[i] === 'current'\"\n [class.font-medium]=\"stepStatuses()[i] === 'current'\"\n [class.text-muted-foreground]=\"stepStatuses()[i] !== 'current'\">\n {{ step.title }}\n </span>\n }\n </li>\n } @else {\n <!-- Vertical Layout -->\n <li\n [class]=\"getItemClasses()\"\n [class.!items-start]=\"!step.description && (step.title || step.icon)\"\n [class.items-center]=\"!step.description && (step.title || step.icon)\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n <!-- Vertical Line -->\n @if (!last) {\n <div [class]=\"lineClasses()\"></div>\n }\n\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content -->\n @if (step.title || step.description) {\n <div class=\"flex min-w-0 flex-col\" [style.padding-top.px]=\"!step.description ? iconWidth() / 5 : 0\">\n @if (step.title) {\n <h3 class=\"leading-tight font-medium\">{{ step.title }}</h3>\n }\n @if (step.description) {\n <p class=\"text-muted-foreground mt-1 text-sm\">{{ step.description }}</p>\n }\n </div>\n }\n </li>\n }\n } @else {\n <!-- Horizontal Layout -->\n <li\n [class]=\"zType() === 'arrow' ? 'flex-1' : 'flex-1 last:flex-none'\"\n [class.cursor-pointer]=\"zClickable() && !step.disabled\"\n [class.cursor-not-allowed]=\"step.disabled\"\n [class.opacity-50]=\"step.disabled\"\n (click)=\"onStepClick(i)\">\n @if (zType() === 'arrow') {\n <!-- Arrow Style -->\n <div [class]=\"getArrowClassesByIndex()[i]\">\n <div class=\"flex items-center gap-3.5\">\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" class=\"shrink-0\" />\n }\n <div class=\"flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-semibold whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"mt-1 truncate text-xs whitespace-nowrap opacity-80\">\n {{ step.description }}\n </p>\n }\n </div>\n </div>\n </div>\n } @else if (zType() === 'dot') {\n <!-- Dot Style: Simple dots with optional labels -->\n <div class=\"flex items-center\">\n <!-- Dot -->\n <span [class]=\"getDotClassesByIndex()[i]\"></span>\n\n <!-- Content (optional) -->\n @if (step.title) {\n <span\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"ms-2 max-w-20 truncate text-sm whitespace-nowrap\"\n [class.text-foreground]=\"stepStatuses()[i] === 'current'\"\n [class.text-muted-foreground]=\"stepStatuses()[i] !== 'current'\">\n {{ step.title }}\n </span>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getDotLineClassesByIndex()[i]\" class=\"mx-2 min-w-8\"></div>\n }\n </div>\n } @else if (zType() === 'inline') {\n <!-- Inline: Icon + Content + Line in one row -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Content Inline -->\n @if (step.title || step.description) {\n <div class=\"ms-3 flex min-w-0 flex-col\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"max-w-30 truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 max-w-30 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n } @else {\n <!-- Default: Icon + Line row, Content below -->\n <div class=\"flex items-center\">\n <!-- Step Icon -->\n <span [class]=\"getIconClassesByStatus()[i]\" class=\"relative! start-auto! shrink-0\">\n @switch (stepStatuses()[i]) {\n @case ('completed') {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else {\n <z-icon zType=\"lucideCheck\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n }\n @case ('error') {\n <z-icon zType=\"lucideX\" [zSize]=\"getIconSizeByIndex()[i]\" />\n }\n @default {\n @if (step.icon) {\n <z-icon [zType]=\"step.icon\" [zSize]=\"getIconSizeByIndex()[i]\" />\n } @else if (zShowNumber()) {\n <span class=\"font-medium\">{{ i + 1 }}</span>\n }\n }\n }\n </span>\n\n <!-- Horizontal Line -->\n @if (!last) {\n <div [class]=\"getConnectorClassesByIndex()[i]\"></div>\n }\n </div>\n\n <!-- Content Below -->\n @if (step.title || step.description) {\n <div\n class=\"z-steps-content mt-3 flex flex-col text-center\"\n [style.width.px]=\"150\"\n [style.margin-left.px]=\"(iconWidth() - 150) / 2\">\n @if (step.title) {\n <h3\n z-tooltip\n [zContent]=\"step.title\"\n [zAutoDetect]=\"true\"\n zPosition=\"top\"\n class=\"truncate text-sm leading-tight font-medium whitespace-nowrap\">\n {{ step.title }}\n </h3>\n }\n @if (step.description) {\n <p\n z-tooltip\n [zContent]=\"step.description\"\n [zAutoDetect]=\"true\"\n zPosition=\"bottom\"\n class=\"text-muted-foreground mt-1 truncate text-xs whitespace-nowrap\">\n {{ step.description }}\n </p>\n }\n </div>\n }\n }\n </li>\n }\n }\n</ol>\n", styles: ["z-steps ol li:not(:last-child)>div[class*=border-s]{height:calc(100% + 2rem)}z-steps ol li[class*=mb-6]:not(:last-child)>div[class*=border-s]{height:calc(100% + 1.5rem)}z-steps ol li[class*=mb-10]:not(:last-child)>div[class*=border-s]{height:calc(100% + 2.5rem)}z-steps .z-steps-arrow-item{position:relative;display:flex;flex-direction:column;justify-content:center;transition:all .2s ease-out}z-steps .z-steps-arrow-item:hover{filter:brightness(.92)}z-steps .z-steps-arrow-first{border-radius:6px 0 0 6px;clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%)}z-steps .z-steps-arrow-middle{margin-left:-8px;padding-left:calc(16px + 1rem);clip-path:polygon(0 0,calc(100% - 16px) 0,100% 50%,calc(100% - 16px) 100%,0 100%,16px 50%)}z-steps .z-steps-arrow-last{margin-left:-8px;padding-left:calc(16px + 1rem);border-radius:0 6px 6px 0;clip-path:polygon(0 0,100% 0,100% 100%,0 100%,16px 50%)}\n"] }]
|
|
332
387
|
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zSteps: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSteps", required: true }] }], zCurrent: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCurrent", required: false }] }], zOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "zOrientation", required: false }] }], zType: [{ type: i0.Input, args: [{ isSignal: true, alias: "zType", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "zClickable", required: false }] }], zShowNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowNumber", required: false }] }], zResponsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "zResponsive", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zOnStepClick: [{ type: i0.Output, args: ["zOnStepClick"] }], zControl: [{ type: i0.Output, args: ["zControl"] }] } });
|
|
333
388
|
|
|
334
389
|
/**
|