@salla.sa/ui-ai-kit-core 1.0.0
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/LICENSE +21 -0
- package/dist/cjs/ai-card.cjs.entry.js +25 -0
- package/dist/cjs/ai-chat-container.cjs.entry.js +138 -0
- package/dist/cjs/ai-chat-header.cjs.entry.js +79 -0
- package/dist/cjs/ai-chat-message.cjs.entry.js +164 -0
- package/dist/cjs/ai-icon.cjs.entry.js +25 -0
- package/dist/cjs/ai-link.cjs.entry.js +34 -0
- package/dist/cjs/ai-loading.cjs.entry.js +77 -0
- package/dist/cjs/ai-message-input.cjs.entry.js +65 -0
- package/dist/cjs/ai-rating.cjs.entry.js +57 -0
- package/dist/cjs/ai-suggestion.cjs.entry.js +31 -0
- package/dist/cjs/ai-voice-input.cjs.entry.js +233 -0
- package/dist/cjs/icon-registry-dmfLA-Dj.js +82 -0
- package/dist/cjs/index-DLJcLHFH.js +1622 -0
- package/dist/cjs/index.cjs.js +7 -0
- package/dist/cjs/loader.cjs.js +12 -0
- package/dist/cjs/ui-ai-kit.cjs.js +24 -0
- package/dist/collection/collection-manifest.json +23 -0
- package/dist/collection/components/ai-card/ai-card.css +40 -0
- package/dist/collection/components/ai-card/ai-card.js +70 -0
- package/dist/collection/components/ai-card/ai-card.stories.js +52 -0
- package/dist/collection/components/ai-chat-container/ai-chat-container.css +137 -0
- package/dist/collection/components/ai-chat-container/ai-chat-container.js +270 -0
- package/dist/collection/components/ai-chat-container/ai-chat-container.stories.js +160 -0
- package/dist/collection/components/ai-chat-header/ai-chat-header.css +186 -0
- package/dist/collection/components/ai-chat-header/ai-chat-header.js +311 -0
- package/dist/collection/components/ai-chat-header/ai-chat-header.stories.js +138 -0
- package/dist/collection/components/ai-chat-message/ai-chat-message.css +304 -0
- package/dist/collection/components/ai-chat-message/ai-chat-message.js +379 -0
- package/dist/collection/components/ai-chat-message/ai-chat-message.stories.js +164 -0
- package/dist/collection/components/ai-icon/ai-icon.css +9 -0
- package/dist/collection/components/ai-icon/ai-icon.js +76 -0
- package/dist/collection/components/ai-link/ai-link.css +62 -0
- package/dist/collection/components/ai-link/ai-link.js +119 -0
- package/dist/collection/components/ai-link/ai-link.stories.js +79 -0
- package/dist/collection/components/ai-loading/ai-loading.css +202 -0
- package/dist/collection/components/ai-loading/ai-loading.js +244 -0
- package/dist/collection/components/ai-loading/ai-loading.stories.js +145 -0
- package/dist/collection/components/ai-message-input/ai-message-input.css +175 -0
- package/dist/collection/components/ai-message-input/ai-message-input.js +192 -0
- package/dist/collection/components/ai-message-input/ai-message-input.stories.js +125 -0
- package/dist/collection/components/ai-rating/ai-rating.css +145 -0
- package/dist/collection/components/ai-rating/ai-rating.js +176 -0
- package/dist/collection/components/ai-rating/ai-rating.stories.js +78 -0
- package/dist/collection/components/ai-suggestion/ai-suggestion.css +69 -0
- package/dist/collection/components/ai-suggestion/ai-suggestion.js +93 -0
- package/dist/collection/components/ai-suggestion/ai-suggestion.stories.js +62 -0
- package/dist/collection/components/ai-voice-input/ai-voice-input.css +136 -0
- package/dist/collection/components/ai-voice-input/ai-voice-input.js +341 -0
- package/dist/collection/components/ai-voice-input/ai-voice-input.stories.js +118 -0
- package/dist/collection/index.js +10 -0
- package/dist/collection/utils/icon-registry.js +78 -0
- package/dist/collection/utils/utils.js +3 -0
- package/dist/components/ai-card.d.ts +11 -0
- package/dist/components/ai-card.js +1 -0
- package/dist/components/ai-chat-container.d.ts +11 -0
- package/dist/components/ai-chat-container.js +1 -0
- package/dist/components/ai-chat-header.d.ts +11 -0
- package/dist/components/ai-chat-header.js +1 -0
- package/dist/components/ai-chat-message.d.ts +11 -0
- package/dist/components/ai-chat-message.js +1 -0
- package/dist/components/ai-icon.d.ts +11 -0
- package/dist/components/ai-icon.js +1 -0
- package/dist/components/ai-link.d.ts +11 -0
- package/dist/components/ai-link.js +1 -0
- package/dist/components/ai-loading.d.ts +11 -0
- package/dist/components/ai-loading.js +1 -0
- package/dist/components/ai-message-input.d.ts +11 -0
- package/dist/components/ai-message-input.js +1 -0
- package/dist/components/ai-rating.d.ts +11 -0
- package/dist/components/ai-rating.js +1 -0
- package/dist/components/ai-suggestion.d.ts +11 -0
- package/dist/components/ai-suggestion.js +1 -0
- package/dist/components/ai-voice-input.d.ts +11 -0
- package/dist/components/ai-voice-input.js +1 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/p-CWjXxYJI.js +1 -0
- package/dist/components/p-CY6emva2.js +1 -0
- package/dist/components/p-DYv5ef4M.js +1 -0
- package/dist/esm/ai-card.entry.js +23 -0
- package/dist/esm/ai-chat-container.entry.js +136 -0
- package/dist/esm/ai-chat-header.entry.js +77 -0
- package/dist/esm/ai-chat-message.entry.js +162 -0
- package/dist/esm/ai-icon.entry.js +23 -0
- package/dist/esm/ai-link.entry.js +32 -0
- package/dist/esm/ai-loading.entry.js +75 -0
- package/dist/esm/ai-message-input.entry.js +63 -0
- package/dist/esm/ai-rating.entry.js +55 -0
- package/dist/esm/ai-suggestion.entry.js +29 -0
- package/dist/esm/ai-voice-input.entry.js +231 -0
- package/dist/esm/icon-registry-DYv5ef4M.js +80 -0
- package/dist/esm/index-7hrZ8FOQ.js +1612 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/loader.js +10 -0
- package/dist/esm/ui-ai-kit.js +20 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/components/ai-card/ai-card.d.ts +7 -0
- package/dist/types/components/ai-card/ai-card.stories.d.ts +7 -0
- package/dist/types/components/ai-chat-container/ai-chat-container.d.ts +28 -0
- package/dist/types/components/ai-chat-container/ai-chat-container.stories.d.ts +7 -0
- package/dist/types/components/ai-chat-header/ai-chat-header.d.ts +38 -0
- package/dist/types/components/ai-chat-header/ai-chat-header.stories.d.ts +8 -0
- package/dist/types/components/ai-chat-message/ai-chat-message.d.ts +27 -0
- package/dist/types/components/ai-chat-message/ai-chat-message.stories.d.ts +10 -0
- package/dist/types/components/ai-icon/ai-icon.d.ts +8 -0
- package/dist/types/components/ai-link/ai-link.d.ts +12 -0
- package/dist/types/components/ai-link/ai-link.stories.d.ts +8 -0
- package/dist/types/components/ai-loading/ai-loading.d.ts +33 -0
- package/dist/types/components/ai-loading/ai-loading.stories.d.ts +10 -0
- package/dist/types/components/ai-message-input/ai-message-input.d.ts +22 -0
- package/dist/types/components/ai-message-input/ai-message-input.stories.d.ts +13 -0
- package/dist/types/components/ai-rating/ai-rating.d.ts +17 -0
- package/dist/types/components/ai-rating/ai-rating.stories.d.ts +8 -0
- package/dist/types/components/ai-suggestion/ai-suggestion.d.ts +10 -0
- package/dist/types/components/ai-suggestion/ai-suggestion.stories.d.ts +8 -0
- package/dist/types/components/ai-voice-input/ai-voice-input.d.ts +43 -0
- package/dist/types/components/ai-voice-input/ai-voice-input.stories.d.ts +9 -0
- package/dist/types/components.d.ts +860 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +1860 -0
- package/dist/types/utils/icon-registry.d.ts +5 -0
- package/dist/types/utils/utils.d.ts +1 -0
- package/dist/ui-ai-kit/index.esm.js +1 -0
- package/dist/ui-ai-kit/p-11facfad.entry.js +1 -0
- package/dist/ui-ai-kit/p-128a2ed4.entry.js +1 -0
- package/dist/ui-ai-kit/p-227bdb8f.entry.js +1 -0
- package/dist/ui-ai-kit/p-455daa17.entry.js +1 -0
- package/dist/ui-ai-kit/p-56163e8c.entry.js +1 -0
- package/dist/ui-ai-kit/p-6d21d0fd.entry.js +1 -0
- package/dist/ui-ai-kit/p-6ddcd77b.entry.js +1 -0
- package/dist/ui-ai-kit/p-7hrZ8FOQ.js +2 -0
- package/dist/ui-ai-kit/p-8e90143e.entry.js +1 -0
- package/dist/ui-ai-kit/p-9938c277.entry.js +1 -0
- package/dist/ui-ai-kit/p-DYv5ef4M.js +1 -0
- package/dist/ui-ai-kit/p-dc5b4a7f.entry.js +1 -0
- package/dist/ui-ai-kit/p-fb1702de.entry.js +1 -0
- package/dist/ui-ai-kit/ui-ai-kit.css +1 -0
- package/dist/ui-ai-kit/ui-ai-kit.esm.js +1 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +77 -0
- package/readme.md +111 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { html, render } from "lit";
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'Chat/Chat Container',
|
|
4
|
+
component: 'ai-chat-container',
|
|
5
|
+
tags: ['autodocs'],
|
|
6
|
+
argTypes: {
|
|
7
|
+
isOpen: {
|
|
8
|
+
control: 'boolean',
|
|
9
|
+
description: 'Controls visibility of the chat panel',
|
|
10
|
+
},
|
|
11
|
+
position: {
|
|
12
|
+
control: { type: 'select' },
|
|
13
|
+
options: ['left', 'right', 'float'],
|
|
14
|
+
description: 'Position of the panel',
|
|
15
|
+
},
|
|
16
|
+
width: {
|
|
17
|
+
control: 'text',
|
|
18
|
+
description: 'Width of the panel (CSS value, e.g., "400px", "30%", "28rem")',
|
|
19
|
+
},
|
|
20
|
+
floatHeight: {
|
|
21
|
+
control: 'text',
|
|
22
|
+
description: 'Height of the panel when position="float" (CSS value, e.g., "600px")',
|
|
23
|
+
},
|
|
24
|
+
autoScroll: {
|
|
25
|
+
control: 'boolean',
|
|
26
|
+
description: 'Enable/disable auto-scroll to latest message',
|
|
27
|
+
},
|
|
28
|
+
showWatermark: {
|
|
29
|
+
control: 'boolean',
|
|
30
|
+
description: 'Show AI watermark in the top half of the container',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
export default meta;
|
|
35
|
+
export const StickyRight = {
|
|
36
|
+
render: args => html `
|
|
37
|
+
<div style="position: relative; height: 600px; background: #f3f4f6;">
|
|
38
|
+
<ai-chat-container
|
|
39
|
+
?is-open="${args.isOpen}"
|
|
40
|
+
position="${args.position}"
|
|
41
|
+
width="${args.width}"
|
|
42
|
+
?auto-scroll="${args.autoScroll}"
|
|
43
|
+
?show-watermark="${args.showWatermark}"
|
|
44
|
+
float-height="${args.floatHeight}"
|
|
45
|
+
></ai-chat-container>
|
|
46
|
+
</div>
|
|
47
|
+
`,
|
|
48
|
+
args: {
|
|
49
|
+
isOpen: true,
|
|
50
|
+
position: 'right',
|
|
51
|
+
width: '28rem',
|
|
52
|
+
autoScroll: true,
|
|
53
|
+
showWatermark: true,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
export const FloatMode = {
|
|
57
|
+
render: args => html `
|
|
58
|
+
<div style="height: 700px; background: #f3f4f6; position: relative;">
|
|
59
|
+
<p style="padding: 2rem; color: #6b7280;">The floating panel appears in the top-left corner. Drag it by the grip icon in the header.</p>
|
|
60
|
+
<ai-chat-container
|
|
61
|
+
?is-open="${args.isOpen}"
|
|
62
|
+
position="${args.position}"
|
|
63
|
+
width="${args.width}"
|
|
64
|
+
float-height="${args.floatHeight}"
|
|
65
|
+
?auto-scroll="${args.autoScroll}"
|
|
66
|
+
?show-watermark="${args.showWatermark}"
|
|
67
|
+
>
|
|
68
|
+
<ai-chat-header slot="header" conversation="AI Assistant" is-draggable></ai-chat-header>
|
|
69
|
+
</ai-chat-container>
|
|
70
|
+
</div>
|
|
71
|
+
`,
|
|
72
|
+
args: {
|
|
73
|
+
isOpen: true,
|
|
74
|
+
position: 'float',
|
|
75
|
+
width: '28rem',
|
|
76
|
+
floatHeight: '600px',
|
|
77
|
+
autoScroll: true,
|
|
78
|
+
showWatermark: true,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
export const ShowcaseConversation = {
|
|
82
|
+
render: () => {
|
|
83
|
+
const steps = JSON.stringify([
|
|
84
|
+
{ id: '1', title: 'مقارنة الباقات المتاحة', status: 'completed' },
|
|
85
|
+
{ id: '2', title: 'تحليل الفروقات والمزايا', status: 'completed' },
|
|
86
|
+
{ id: '3', title: 'تجهيز التوصية المناسبة', status: 'executing' },
|
|
87
|
+
{ id: '4', title: 'إعداد الروابط والمصادر', status: 'pending' },
|
|
88
|
+
]);
|
|
89
|
+
const t = (offsetMs) => new Date(Date.now() - offsetMs).toISOString();
|
|
90
|
+
const comparisonContent = `باقة **بلس** مناسبة للمتاجر الصغيرة والمتوسطة، بينما باقة **برو** مصممة للمتاجر الكبيرة اللي تحتاج منتجات غير محدودة وعمولات أقل ودعم فني على مدار الساعة.\n\n**التوصية:** إذا كنت تتوقع نمواً سريعاً، باقة **برو** هي الأنسب.`;
|
|
91
|
+
const root = document.createElement('div');
|
|
92
|
+
let showVoice = false;
|
|
93
|
+
const update = () => {
|
|
94
|
+
render(html `
|
|
95
|
+
<div style="position: relative; height: 700px; background: #f3f4f6;">
|
|
96
|
+
<ai-chat-container is-open position="float" float-height="800px" width="28rem" auto-scroll>
|
|
97
|
+
<ai-chat-header slot="header" is-draggable mode="agent" conversation="مساعد سلة"></ai-chat-header>
|
|
98
|
+
|
|
99
|
+
<div style="padding:1rem; display:flex; flex-direction:column; gap:0.75rem;">
|
|
100
|
+
<ai-chat-message role="agent" enable-regenerate content="أهلاً وسهلاً! أنا مساعد سلة الذكي 🤖 كيف أقدر أساعدك اليوم؟" agent-name="سلة AI" timestamp="${t(300000)}">
|
|
101
|
+
<div style="display:flex; flex-wrap:wrap; gap:0.5rem;">
|
|
102
|
+
<ai-suggestion label="وش الباقات المتاحة؟"></ai-suggestion>
|
|
103
|
+
<ai-suggestion label="كيف أرقي باقتي؟"></ai-suggestion>
|
|
104
|
+
<ai-suggestion label="مقارنة بلس وبرو"></ai-suggestion>
|
|
105
|
+
</div>
|
|
106
|
+
</ai-chat-message>
|
|
107
|
+
|
|
108
|
+
<ai-chat-message role="user" content="وش الفرق بين باقة بلس وبرو" timestamp="${t(240000)}"></ai-chat-message>
|
|
109
|
+
|
|
110
|
+
<ai-loading mode="thinking" status-text="جاري التحميل..."></ai-loading>
|
|
111
|
+
|
|
112
|
+
<ai-loading mode="steps" status-text="جاري التحليل..." steps="${steps}" expanded collapsible></ai-loading>
|
|
113
|
+
|
|
114
|
+
<ai-chat-message role="agent" .content=${comparisonContent} format="markdown" agent-name="سلة AI" timestamp="${t(180000)}" show-actions>
|
|
115
|
+
<div style="display:flex; flex-wrap:wrap; gap:0.5rem;">
|
|
116
|
+
<ai-suggestion label="كيف أرقي باقتي؟"></ai-suggestion>
|
|
117
|
+
<ai-suggestion label="ما هي طرق الدفع؟"></ai-suggestion>
|
|
118
|
+
</div>
|
|
119
|
+
</ai-chat-message>
|
|
120
|
+
<ai-card>
|
|
121
|
+
<p >للاطلاع على التفاصيل الكاملة لجميع الباقات وأسعارها:</p>
|
|
122
|
+
<ai-link label="صفحة الباقات" href="#"></ai-link>
|
|
123
|
+
</ai-card>
|
|
124
|
+
|
|
125
|
+
<ai-chat-message role="user" content="كيف أرقي باقتي؟" timestamp="${t(120000)}"></ai-chat-message>
|
|
126
|
+
|
|
127
|
+
<ai-chat-message
|
|
128
|
+
role="agent"
|
|
129
|
+
.content=${'ترقية باقتك سهلة وسريعة! اتبع الخطوات التالية:\n\n1. سجّل دخول إلى لوحة تحكم سلة\n2. اذهب إلى **الإعدادات** ← **الباقة والفوترة**\n3. اختر الباقة المطلوبة\n4. أكمل عملية الدفع\n\nسيتم تفعيل الباقة الجديدة فوراً بعد إتمام الدفع ✅'}
|
|
130
|
+
format="markdown"
|
|
131
|
+
agent-name="سلة AI"
|
|
132
|
+
timestamp="${t(60000)}"
|
|
133
|
+
feedback-value="up"
|
|
134
|
+
show-actions
|
|
135
|
+
></ai-chat-message>
|
|
136
|
+
<ai-card>
|
|
137
|
+
<ai-rating question="كيف كانت تجربتك مع المساعد؟" subtitle="رأيك يساعدنا على التحسين"></ai-rating>
|
|
138
|
+
</ai-card>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
${showVoice
|
|
142
|
+
? html `<ai-voice-input
|
|
143
|
+
slot="footer"
|
|
144
|
+
auto-start
|
|
145
|
+
@audioRecorded=${() => { showVoice = false; update(); }}
|
|
146
|
+
@recordingCancel=${() => { showVoice = false; update(); }}
|
|
147
|
+
></ai-voice-input>`
|
|
148
|
+
: html `<ai-message-input
|
|
149
|
+
slot="footer"
|
|
150
|
+
placeholder="اكتب رسالتك هنا..."
|
|
151
|
+
@voiceButtonClick=${() => { showVoice = true; update(); }}
|
|
152
|
+
></ai-message-input>`}
|
|
153
|
+
</ai-chat-container>
|
|
154
|
+
</div>
|
|
155
|
+
`, root);
|
|
156
|
+
};
|
|
157
|
+
update();
|
|
158
|
+
return root;
|
|
159
|
+
},
|
|
160
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
font-family: var(--ai-font-family, "PingARLT", sans-serif);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/* ── Container ──────────────────────────────────────────────────── */
|
|
7
|
+
.header-container {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
gap: 8px;
|
|
11
|
+
padding: 16px;
|
|
12
|
+
background: var(--ai-bg-card, white);
|
|
13
|
+
border-bottom: 1px solid var(--ai-border-light, #f4f4f4);
|
|
14
|
+
width: 100%;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.header-container {
|
|
19
|
+
direction: rtl;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* ── Action & Back Buttons ──────────────────────────────────────── */
|
|
23
|
+
.drag-btn {
|
|
24
|
+
cursor: grab;
|
|
25
|
+
color: var(--ai-text-muted);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.drag-btn:active {
|
|
29
|
+
cursor: grabbing;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.action-btn,
|
|
33
|
+
.back-btn {
|
|
34
|
+
width: 40px;
|
|
35
|
+
height: 40px;
|
|
36
|
+
padding: 4px;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
background: var(--ai-bg-card, white);
|
|
41
|
+
border: none;
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
flex-shrink: 0;
|
|
45
|
+
color: var(--ai-text-primary);
|
|
46
|
+
transition: background 0.15s ease;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.action-btn:hover,
|
|
50
|
+
.back-btn:hover {
|
|
51
|
+
background: var(--ai-bg-surface, #f9fafb);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.action-btn:focus-visible,
|
|
55
|
+
.back-btn:focus-visible {
|
|
56
|
+
outline: 2px solid var(--ai-focus-ring);
|
|
57
|
+
outline-offset: 2px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.action-btn:active,
|
|
61
|
+
.back-btn:active {
|
|
62
|
+
background: var(--ai-bg-surface, #f3f4f6);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ── Actions Group ──────────────────────────────────────────────── */
|
|
66
|
+
.actions {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
gap: 8px;
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── Content Area ───────────────────────────────────────────────── */
|
|
74
|
+
.content {
|
|
75
|
+
flex: 1 0 0;
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: flex-start;
|
|
79
|
+
min-width: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.content.agent {
|
|
83
|
+
gap: 4px;
|
|
84
|
+
height: 40px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.content.human {
|
|
88
|
+
gap: 8px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* ── Dropdown Trigger (agent mode) ──────────────────────────────── */
|
|
92
|
+
.dropdown-trigger {
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
gap: 4px;
|
|
96
|
+
background: none;
|
|
97
|
+
border: none;
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
padding: 0;
|
|
100
|
+
flex-shrink: 0;
|
|
101
|
+
color: var(--ai-text-primary);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.dropdown-trigger:focus-visible {
|
|
105
|
+
outline: 2px solid var(--ai-focus-ring);
|
|
106
|
+
outline-offset: 2px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* ── Title (agent mode) ─────────────────────────────────────────── */
|
|
110
|
+
.title {
|
|
111
|
+
font-size: 16px;
|
|
112
|
+
font-weight: 700;
|
|
113
|
+
color: var(--ai-text-primary, #444444);
|
|
114
|
+
white-space: nowrap;
|
|
115
|
+
line-height: normal;
|
|
116
|
+
min-width: 0;
|
|
117
|
+
overflow: hidden;
|
|
118
|
+
text-overflow: ellipsis;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ── Avatar & Online Dot (human mode) ──────────────────────────── */
|
|
122
|
+
.avatar-wrapper {
|
|
123
|
+
position: relative;
|
|
124
|
+
width: 40px;
|
|
125
|
+
height: 40px;
|
|
126
|
+
flex-shrink: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.avatar {
|
|
130
|
+
width: 40px;
|
|
131
|
+
height: 40px;
|
|
132
|
+
border-radius: 9999px;
|
|
133
|
+
border: 1px solid var(--ai-border-default, #eeeeee);
|
|
134
|
+
object-fit: cover;
|
|
135
|
+
display: block;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.online-dot {
|
|
139
|
+
position: absolute;
|
|
140
|
+
bottom: 0;
|
|
141
|
+
left: 0;
|
|
142
|
+
width: 10px;
|
|
143
|
+
height: 10px;
|
|
144
|
+
display: inline-flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
color: var(--ai-bg-card); /* used as stroke to match card bg in both themes */
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* ── Text Block (human mode) ────────────────────────────────────── */
|
|
151
|
+
.text-block {
|
|
152
|
+
display: flex;
|
|
153
|
+
flex-direction: column;
|
|
154
|
+
align-items: flex-end;
|
|
155
|
+
gap: 0;
|
|
156
|
+
flex-shrink: 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
.agent-name {
|
|
161
|
+
font-size: 14px;
|
|
162
|
+
font-weight: 500;
|
|
163
|
+
color: var(--ai-text-primary, #333333);
|
|
164
|
+
line-height: 20px;
|
|
165
|
+
white-space: nowrap;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.agent-status {
|
|
169
|
+
font-size: 14px;
|
|
170
|
+
font-weight: 400;
|
|
171
|
+
color: var(--ai-text-secondary, #737373);
|
|
172
|
+
line-height: 20px;
|
|
173
|
+
white-space: nowrap;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* ── Icon Wrapper ───────────────────────────────────────────────── */
|
|
177
|
+
.icon-wrap {
|
|
178
|
+
display: inline-flex;
|
|
179
|
+
align-items: center;
|
|
180
|
+
justify-content: center;
|
|
181
|
+
flex-shrink: 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.icon-wrap svg {
|
|
185
|
+
display: block;
|
|
186
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { Host, h } from "@stencil/core";
|
|
2
|
+
import { iconRegistry } from "../../utils/icon-registry";
|
|
3
|
+
export class AiChatHeader {
|
|
4
|
+
/** Layout variant */
|
|
5
|
+
mode = 'agent';
|
|
6
|
+
/** Agent mode: conversation title */
|
|
7
|
+
conversation = 'محادثة جديدة';
|
|
8
|
+
/** Human mode: agent's display name */
|
|
9
|
+
agentName = '';
|
|
10
|
+
/** Human mode: status label (e.g. "Active") */
|
|
11
|
+
agentStatus = '';
|
|
12
|
+
/** Human mode: avatar image URL */
|
|
13
|
+
agentAvatar = '';
|
|
14
|
+
/** Human mode: show the back button */
|
|
15
|
+
showBack = true;
|
|
16
|
+
isDraggable = false;
|
|
17
|
+
/** Cancel / close button */
|
|
18
|
+
closeClick;
|
|
19
|
+
/** Pencil-edit button (agent mode) */
|
|
20
|
+
editClick;
|
|
21
|
+
/** Title / chevron click → open conversation list (agent mode) */
|
|
22
|
+
dropdownClick;
|
|
23
|
+
/** Chevron-down button (human mode) */
|
|
24
|
+
moreClick;
|
|
25
|
+
/** Back-arrow button (human mode) */
|
|
26
|
+
backClick;
|
|
27
|
+
/**
|
|
28
|
+
* Fired on pointerdown of the drag handle.
|
|
29
|
+
* Composed + bubbling so ai-chat-container can receive it across shadow roots.
|
|
30
|
+
*/
|
|
31
|
+
headerDragStart;
|
|
32
|
+
renderIcon(name, width, height) {
|
|
33
|
+
const icon = iconRegistry[name];
|
|
34
|
+
if (!icon)
|
|
35
|
+
return null;
|
|
36
|
+
const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
|
|
37
|
+
return h("span", { class: "icon-wrap", innerHTML: svg });
|
|
38
|
+
}
|
|
39
|
+
renderAgentMode() {
|
|
40
|
+
return [
|
|
41
|
+
this.isDraggable && (h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
|
|
44
|
+
} }, this.renderIcon('drag', 11, 15))),
|
|
45
|
+
h("div", { class: "content agent" }, h("span", { class: "title" }, this.conversation), h("button", { class: "dropdown-trigger", onClick: () => this.dropdownClick.emit() }, this.renderIcon('chevron-down', 24, 24))),
|
|
46
|
+
h("div", { class: "actions" }, h("button", { class: "action-btn", onClick: () => this.editClick.emit() }, this.renderIcon('pencil-edit', 22, 22)), h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
renderHumanMode() {
|
|
50
|
+
return [
|
|
51
|
+
this.isDraggable && (h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
|
|
54
|
+
} }, this.renderIcon('drag', 11, 15))),
|
|
55
|
+
h("div", { class: "content human" }, this.showBack && (h("button", { class: "back-btn", onClick: () => this.backClick.emit() }, this.renderIcon('arrow-right', 24, 24))), h("div", { class: "avatar-wrapper" }, h("img", { class: "avatar", src: this.agentAvatar, alt: this.agentName }), h("span", { class: "online-dot" }, this.renderIcon('online-dot', 10, 10))), h("div", { class: "text-block" }, h("span", { class: "agent-name" }, this.agentName), h("span", { class: "agent-status" }, this.agentStatus))),
|
|
56
|
+
h("div", { class: "actions" }, h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
render() {
|
|
60
|
+
return (h(Host, { key: '93fe332abe1339f7235aa18717d63aa65d9aac13' }, h("div", { key: 'b496695911f7d1f959c4f98506b0d230e77a86c3', class: "header-container" }, this.mode === 'agent' ? this.renderAgentMode() : this.renderHumanMode())));
|
|
61
|
+
}
|
|
62
|
+
static get is() { return "ai-chat-header"; }
|
|
63
|
+
static get encapsulation() { return "shadow"; }
|
|
64
|
+
static get originalStyleUrls() {
|
|
65
|
+
return {
|
|
66
|
+
"$": ["ai-chat-header.css"]
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
static get styleUrls() {
|
|
70
|
+
return {
|
|
71
|
+
"$": ["ai-chat-header.css"]
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
static get properties() {
|
|
75
|
+
return {
|
|
76
|
+
"mode": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"mutable": false,
|
|
79
|
+
"complexType": {
|
|
80
|
+
"original": "'agent' | 'human'",
|
|
81
|
+
"resolved": "\"agent\" | \"human\"",
|
|
82
|
+
"references": {}
|
|
83
|
+
},
|
|
84
|
+
"required": false,
|
|
85
|
+
"optional": false,
|
|
86
|
+
"docs": {
|
|
87
|
+
"tags": [],
|
|
88
|
+
"text": "Layout variant"
|
|
89
|
+
},
|
|
90
|
+
"getter": false,
|
|
91
|
+
"setter": false,
|
|
92
|
+
"reflect": false,
|
|
93
|
+
"attribute": "mode",
|
|
94
|
+
"defaultValue": "'agent'"
|
|
95
|
+
},
|
|
96
|
+
"conversation": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"mutable": false,
|
|
99
|
+
"complexType": {
|
|
100
|
+
"original": "string",
|
|
101
|
+
"resolved": "string",
|
|
102
|
+
"references": {}
|
|
103
|
+
},
|
|
104
|
+
"required": false,
|
|
105
|
+
"optional": false,
|
|
106
|
+
"docs": {
|
|
107
|
+
"tags": [],
|
|
108
|
+
"text": "Agent mode: conversation title"
|
|
109
|
+
},
|
|
110
|
+
"getter": false,
|
|
111
|
+
"setter": false,
|
|
112
|
+
"reflect": false,
|
|
113
|
+
"attribute": "conversation",
|
|
114
|
+
"defaultValue": "'\u0645\u062D\u0627\u062F\u062B\u0629 \u062C\u062F\u064A\u062F\u0629'"
|
|
115
|
+
},
|
|
116
|
+
"agentName": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"mutable": false,
|
|
119
|
+
"complexType": {
|
|
120
|
+
"original": "string",
|
|
121
|
+
"resolved": "string",
|
|
122
|
+
"references": {}
|
|
123
|
+
},
|
|
124
|
+
"required": false,
|
|
125
|
+
"optional": false,
|
|
126
|
+
"docs": {
|
|
127
|
+
"tags": [],
|
|
128
|
+
"text": "Human mode: agent's display name"
|
|
129
|
+
},
|
|
130
|
+
"getter": false,
|
|
131
|
+
"setter": false,
|
|
132
|
+
"reflect": false,
|
|
133
|
+
"attribute": "agent-name",
|
|
134
|
+
"defaultValue": "''"
|
|
135
|
+
},
|
|
136
|
+
"agentStatus": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"mutable": false,
|
|
139
|
+
"complexType": {
|
|
140
|
+
"original": "string",
|
|
141
|
+
"resolved": "string",
|
|
142
|
+
"references": {}
|
|
143
|
+
},
|
|
144
|
+
"required": false,
|
|
145
|
+
"optional": false,
|
|
146
|
+
"docs": {
|
|
147
|
+
"tags": [],
|
|
148
|
+
"text": "Human mode: status label (e.g. \"Active\")"
|
|
149
|
+
},
|
|
150
|
+
"getter": false,
|
|
151
|
+
"setter": false,
|
|
152
|
+
"reflect": false,
|
|
153
|
+
"attribute": "agent-status",
|
|
154
|
+
"defaultValue": "''"
|
|
155
|
+
},
|
|
156
|
+
"agentAvatar": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"mutable": false,
|
|
159
|
+
"complexType": {
|
|
160
|
+
"original": "string",
|
|
161
|
+
"resolved": "string",
|
|
162
|
+
"references": {}
|
|
163
|
+
},
|
|
164
|
+
"required": false,
|
|
165
|
+
"optional": false,
|
|
166
|
+
"docs": {
|
|
167
|
+
"tags": [],
|
|
168
|
+
"text": "Human mode: avatar image URL"
|
|
169
|
+
},
|
|
170
|
+
"getter": false,
|
|
171
|
+
"setter": false,
|
|
172
|
+
"reflect": false,
|
|
173
|
+
"attribute": "agent-avatar",
|
|
174
|
+
"defaultValue": "''"
|
|
175
|
+
},
|
|
176
|
+
"showBack": {
|
|
177
|
+
"type": "boolean",
|
|
178
|
+
"mutable": false,
|
|
179
|
+
"complexType": {
|
|
180
|
+
"original": "boolean",
|
|
181
|
+
"resolved": "boolean",
|
|
182
|
+
"references": {}
|
|
183
|
+
},
|
|
184
|
+
"required": false,
|
|
185
|
+
"optional": false,
|
|
186
|
+
"docs": {
|
|
187
|
+
"tags": [],
|
|
188
|
+
"text": "Human mode: show the back button"
|
|
189
|
+
},
|
|
190
|
+
"getter": false,
|
|
191
|
+
"setter": false,
|
|
192
|
+
"reflect": false,
|
|
193
|
+
"attribute": "show-back",
|
|
194
|
+
"defaultValue": "true"
|
|
195
|
+
},
|
|
196
|
+
"isDraggable": {
|
|
197
|
+
"type": "boolean",
|
|
198
|
+
"mutable": false,
|
|
199
|
+
"complexType": {
|
|
200
|
+
"original": "boolean",
|
|
201
|
+
"resolved": "boolean",
|
|
202
|
+
"references": {}
|
|
203
|
+
},
|
|
204
|
+
"required": false,
|
|
205
|
+
"optional": false,
|
|
206
|
+
"docs": {
|
|
207
|
+
"tags": [],
|
|
208
|
+
"text": ""
|
|
209
|
+
},
|
|
210
|
+
"getter": false,
|
|
211
|
+
"setter": false,
|
|
212
|
+
"reflect": false,
|
|
213
|
+
"attribute": "is-draggable",
|
|
214
|
+
"defaultValue": "false"
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
static get events() {
|
|
219
|
+
return [{
|
|
220
|
+
"method": "closeClick",
|
|
221
|
+
"name": "closeClick",
|
|
222
|
+
"bubbles": true,
|
|
223
|
+
"cancelable": true,
|
|
224
|
+
"composed": true,
|
|
225
|
+
"docs": {
|
|
226
|
+
"tags": [],
|
|
227
|
+
"text": "Cancel / close button"
|
|
228
|
+
},
|
|
229
|
+
"complexType": {
|
|
230
|
+
"original": "void",
|
|
231
|
+
"resolved": "void",
|
|
232
|
+
"references": {}
|
|
233
|
+
}
|
|
234
|
+
}, {
|
|
235
|
+
"method": "editClick",
|
|
236
|
+
"name": "editClick",
|
|
237
|
+
"bubbles": true,
|
|
238
|
+
"cancelable": true,
|
|
239
|
+
"composed": true,
|
|
240
|
+
"docs": {
|
|
241
|
+
"tags": [],
|
|
242
|
+
"text": "Pencil-edit button (agent mode)"
|
|
243
|
+
},
|
|
244
|
+
"complexType": {
|
|
245
|
+
"original": "void",
|
|
246
|
+
"resolved": "void",
|
|
247
|
+
"references": {}
|
|
248
|
+
}
|
|
249
|
+
}, {
|
|
250
|
+
"method": "dropdownClick",
|
|
251
|
+
"name": "dropdownClick",
|
|
252
|
+
"bubbles": true,
|
|
253
|
+
"cancelable": true,
|
|
254
|
+
"composed": true,
|
|
255
|
+
"docs": {
|
|
256
|
+
"tags": [],
|
|
257
|
+
"text": "Title / chevron click \u2192 open conversation list (agent mode)"
|
|
258
|
+
},
|
|
259
|
+
"complexType": {
|
|
260
|
+
"original": "void",
|
|
261
|
+
"resolved": "void",
|
|
262
|
+
"references": {}
|
|
263
|
+
}
|
|
264
|
+
}, {
|
|
265
|
+
"method": "moreClick",
|
|
266
|
+
"name": "moreClick",
|
|
267
|
+
"bubbles": true,
|
|
268
|
+
"cancelable": true,
|
|
269
|
+
"composed": true,
|
|
270
|
+
"docs": {
|
|
271
|
+
"tags": [],
|
|
272
|
+
"text": "Chevron-down button (human mode)"
|
|
273
|
+
},
|
|
274
|
+
"complexType": {
|
|
275
|
+
"original": "void",
|
|
276
|
+
"resolved": "void",
|
|
277
|
+
"references": {}
|
|
278
|
+
}
|
|
279
|
+
}, {
|
|
280
|
+
"method": "backClick",
|
|
281
|
+
"name": "backClick",
|
|
282
|
+
"bubbles": true,
|
|
283
|
+
"cancelable": true,
|
|
284
|
+
"composed": true,
|
|
285
|
+
"docs": {
|
|
286
|
+
"tags": [],
|
|
287
|
+
"text": "Back-arrow button (human mode)"
|
|
288
|
+
},
|
|
289
|
+
"complexType": {
|
|
290
|
+
"original": "void",
|
|
291
|
+
"resolved": "void",
|
|
292
|
+
"references": {}
|
|
293
|
+
}
|
|
294
|
+
}, {
|
|
295
|
+
"method": "headerDragStart",
|
|
296
|
+
"name": "headerDragStart",
|
|
297
|
+
"bubbles": true,
|
|
298
|
+
"cancelable": true,
|
|
299
|
+
"composed": true,
|
|
300
|
+
"docs": {
|
|
301
|
+
"tags": [],
|
|
302
|
+
"text": "Fired on pointerdown of the drag handle.\nComposed + bubbling so ai-chat-container can receive it across shadow roots."
|
|
303
|
+
},
|
|
304
|
+
"complexType": {
|
|
305
|
+
"original": "{ clientX: number; clientY: number }",
|
|
306
|
+
"resolved": "{ clientX: number; clientY: number; }",
|
|
307
|
+
"references": {}
|
|
308
|
+
}
|
|
309
|
+
}];
|
|
310
|
+
}
|
|
311
|
+
}
|