@salla.sa/ui-ai-kit-core 1.1.0 → 2.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.
Files changed (147) hide show
  1. package/dist/cjs/ai-card.cjs.entry.js +2 -2
  2. package/dist/cjs/ai-chat-container.cjs.entry.js +84 -57
  3. package/dist/cjs/ai-chat-header.cjs.entry.js +29 -19
  4. package/dist/cjs/ai-chat-message.cjs.entry.js +1456 -21
  5. package/dist/cjs/ai-conversation-list.cjs.entry.js +80 -0
  6. package/dist/cjs/ai-conversation-summary.cjs.entry.js +33 -0
  7. package/dist/cjs/ai-icon.cjs.entry.js +2 -2
  8. package/dist/cjs/ai-link.cjs.entry.js +4 -4
  9. package/dist/cjs/ai-loading.cjs.entry.js +35 -22
  10. package/dist/cjs/ai-message-input.cjs.entry.js +48 -15
  11. package/dist/cjs/ai-rating.cjs.entry.js +2 -2
  12. package/dist/cjs/ai-route-decision.cjs.entry.js +48 -0
  13. package/dist/cjs/ai-suggestion.cjs.entry.js +4 -4
  14. package/dist/cjs/ai-voice-input.cjs.entry.js +75 -21
  15. package/dist/cjs/{icon-registry-dmfLA-Dj.js → icon-registry-BKb9-2Nt.js} +24 -0
  16. package/dist/cjs/{index-DLJcLHFH.js → index-BkNg07SW.js} +1 -1
  17. package/dist/cjs/loader.cjs.js +2 -2
  18. package/dist/cjs/ui-ai-kit.cjs.js +2 -2
  19. package/dist/collection/collection-manifest.json +3 -0
  20. package/dist/collection/components/ai-card/ai-card.css +5 -8
  21. package/dist/collection/components/ai-chat-container/ai-chat-container.css +17 -14
  22. package/dist/collection/components/ai-chat-container/ai-chat-container.js +125 -53
  23. package/dist/collection/components/ai-chat-header/ai-chat-header.css +50 -17
  24. package/dist/collection/components/ai-chat-header/ai-chat-header.js +53 -18
  25. package/dist/collection/components/ai-chat-message/ai-chat-message.css +47 -38
  26. package/dist/collection/components/ai-chat-message/ai-chat-message.js +68 -18
  27. package/dist/collection/components/ai-conversation-list/ai-conversation-list.css +196 -0
  28. package/dist/collection/components/ai-conversation-list/ai-conversation-list.js +176 -0
  29. package/dist/collection/components/ai-conversation-summary/ai-conversation-summary.css +103 -0
  30. package/dist/collection/components/ai-conversation-summary/ai-conversation-summary.js +118 -0
  31. package/dist/collection/components/ai-icon/ai-icon.js +1 -1
  32. package/dist/collection/components/ai-link/ai-link.css +3 -7
  33. package/dist/collection/components/ai-link/ai-link.js +1 -1
  34. package/dist/collection/components/ai-loading/ai-loading.css +149 -20
  35. package/dist/collection/components/ai-loading/ai-loading.js +100 -23
  36. package/dist/collection/components/ai-message-input/ai-message-input.css +41 -37
  37. package/dist/collection/components/ai-message-input/ai-message-input.js +100 -19
  38. package/dist/collection/components/ai-rating/ai-rating.css +8 -14
  39. package/dist/collection/components/ai-route-decision/ai-route-decision.css +132 -0
  40. package/dist/collection/components/ai-route-decision/ai-route-decision.js +195 -0
  41. package/dist/collection/components/ai-suggestion/ai-suggestion.css +5 -11
  42. package/dist/collection/components/ai-suggestion/ai-suggestion.js +2 -2
  43. package/dist/collection/components/ai-voice-input/ai-voice-input.css +27 -22
  44. package/dist/collection/components/ai-voice-input/ai-voice-input.js +116 -20
  45. package/dist/collection/utils/icon-registry.js +24 -0
  46. package/dist/components/ai-card.js +1 -1
  47. package/dist/components/ai-chat-container.js +1 -1
  48. package/dist/components/ai-chat-header.js +1 -1
  49. package/dist/components/ai-chat-message.js +2 -1
  50. package/dist/components/ai-conversation-list.d.ts +11 -0
  51. package/dist/components/ai-conversation-list.js +1 -0
  52. package/dist/components/ai-conversation-summary.d.ts +11 -0
  53. package/dist/components/ai-conversation-summary.js +1 -0
  54. package/dist/components/ai-icon.js +1 -1
  55. package/dist/components/ai-link.js +1 -1
  56. package/dist/components/ai-loading.js +1 -1
  57. package/dist/components/ai-message-input.js +1 -1
  58. package/dist/components/ai-rating.js +1 -1
  59. package/dist/components/ai-route-decision.d.ts +11 -0
  60. package/dist/components/ai-route-decision.js +1 -0
  61. package/dist/components/ai-suggestion.js +1 -1
  62. package/dist/components/ai-voice-input.js +1 -1
  63. package/dist/components/index.js +1 -1
  64. package/dist/components/p-CX1Yp79q.js +1 -0
  65. package/dist/components/p-DnO4dikr.js +1 -0
  66. package/dist/components/{p-CY6emva2.js → p-Dr2tAPV7.js} +1 -1
  67. package/dist/{ui-ai-kit/p-DYv5ef4M.js → components/p-SJZ6Ujn9.js} +1 -1
  68. package/dist/esm/ai-card.entry.js +2 -2
  69. package/dist/esm/ai-chat-container.entry.js +84 -57
  70. package/dist/esm/ai-chat-header.entry.js +29 -19
  71. package/dist/esm/ai-chat-message.entry.js +1456 -21
  72. package/dist/esm/ai-conversation-list.entry.js +78 -0
  73. package/dist/esm/ai-conversation-summary.entry.js +31 -0
  74. package/dist/esm/ai-icon.entry.js +2 -2
  75. package/dist/esm/ai-link.entry.js +4 -4
  76. package/dist/esm/ai-loading.entry.js +35 -22
  77. package/dist/esm/ai-message-input.entry.js +48 -15
  78. package/dist/esm/ai-rating.entry.js +2 -2
  79. package/dist/esm/ai-route-decision.entry.js +46 -0
  80. package/dist/esm/ai-suggestion.entry.js +4 -4
  81. package/dist/esm/ai-voice-input.entry.js +75 -21
  82. package/dist/esm/{icon-registry-DYv5ef4M.js → icon-registry-SJZ6Ujn9.js} +24 -0
  83. package/dist/esm/{index-7hrZ8FOQ.js → index-B0yIzgh4.js} +1 -1
  84. package/dist/esm/loader.js +3 -3
  85. package/dist/esm/ui-ai-kit.js +3 -3
  86. package/dist/types/components/ai-chat-container/ai-chat-container.d.ts +11 -1
  87. package/dist/types/components/ai-chat-header/ai-chat-header.d.ts +7 -2
  88. package/dist/types/components/ai-conversation-list/ai-conversation-list.d.ts +24 -0
  89. package/dist/types/components/ai-conversation-summary/ai-conversation-summary.d.ts +12 -0
  90. package/dist/types/components/ai-loading/ai-loading.d.ts +12 -6
  91. package/dist/types/components/ai-message-input/ai-message-input.d.ts +17 -3
  92. package/dist/types/components/ai-route-decision/ai-route-decision.d.ts +21 -0
  93. package/dist/types/components/ai-voice-input/ai-voice-input.d.ts +7 -0
  94. package/dist/types/components.d.ts +335 -11
  95. package/dist/types/index.d.ts +2 -0
  96. package/dist/types/utils/icon-registry.d.ts +1 -1
  97. package/dist/ui-ai-kit/p-2955439f.entry.js +1 -0
  98. package/dist/ui-ai-kit/p-5c9e9822.entry.js +1 -0
  99. package/dist/ui-ai-kit/p-5caf1c38.entry.js +1 -0
  100. package/dist/ui-ai-kit/p-74c5c83f.entry.js +1 -0
  101. package/dist/ui-ai-kit/p-76195745.entry.js +1 -0
  102. package/dist/ui-ai-kit/p-79c78d8e.entry.js +1 -0
  103. package/dist/ui-ai-kit/p-87e9739b.entry.js +1 -0
  104. package/dist/ui-ai-kit/p-9c4c6c01.entry.js +1 -0
  105. package/dist/ui-ai-kit/p-B0yIzgh4.js +2 -0
  106. package/dist/{components/p-DYv5ef4M.js → ui-ai-kit/p-SJZ6Ujn9.js} +1 -1
  107. package/dist/ui-ai-kit/p-a099fcfb.entry.js +1 -0
  108. package/dist/ui-ai-kit/p-b28af13a.entry.js +1 -0
  109. package/dist/ui-ai-kit/p-d1bb1ad0.entry.js +1 -0
  110. package/dist/ui-ai-kit/p-eb0c7e7a.entry.js +1 -0
  111. package/dist/ui-ai-kit/{p-455daa17.entry.js → p-eec6f083.entry.js} +1 -1
  112. package/dist/ui-ai-kit/p-ef07638f.entry.js +2 -0
  113. package/dist/ui-ai-kit/ui-ai-kit.css +1 -1
  114. package/dist/ui-ai-kit/ui-ai-kit.esm.js +1 -1
  115. package/package.json +5 -13
  116. package/dist/collection/components/ai-card/ai-card.stories.js +0 -52
  117. package/dist/collection/components/ai-chat-container/ai-chat-container.stories.js +0 -160
  118. package/dist/collection/components/ai-chat-header/ai-chat-header.stories.js +0 -138
  119. package/dist/collection/components/ai-chat-message/ai-chat-message.stories.js +0 -164
  120. package/dist/collection/components/ai-link/ai-link.stories.js +0 -79
  121. package/dist/collection/components/ai-loading/ai-loading.stories.js +0 -145
  122. package/dist/collection/components/ai-message-input/ai-message-input.stories.js +0 -125
  123. package/dist/collection/components/ai-rating/ai-rating.stories.js +0 -78
  124. package/dist/collection/components/ai-suggestion/ai-suggestion.stories.js +0 -62
  125. package/dist/collection/components/ai-voice-input/ai-voice-input.stories.js +0 -118
  126. package/dist/components/p-CWjXxYJI.js +0 -1
  127. package/dist/types/components/ai-card/ai-card.stories.d.ts +0 -7
  128. package/dist/types/components/ai-chat-container/ai-chat-container.stories.d.ts +0 -7
  129. package/dist/types/components/ai-chat-header/ai-chat-header.stories.d.ts +0 -8
  130. package/dist/types/components/ai-chat-message/ai-chat-message.stories.d.ts +0 -10
  131. package/dist/types/components/ai-link/ai-link.stories.d.ts +0 -8
  132. package/dist/types/components/ai-loading/ai-loading.stories.d.ts +0 -10
  133. package/dist/types/components/ai-message-input/ai-message-input.stories.d.ts +0 -13
  134. package/dist/types/components/ai-rating/ai-rating.stories.d.ts +0 -8
  135. package/dist/types/components/ai-suggestion/ai-suggestion.stories.d.ts +0 -8
  136. package/dist/types/components/ai-voice-input/ai-voice-input.stories.d.ts +0 -9
  137. package/dist/ui-ai-kit/p-11facfad.entry.js +0 -1
  138. package/dist/ui-ai-kit/p-128a2ed4.entry.js +0 -1
  139. package/dist/ui-ai-kit/p-227bdb8f.entry.js +0 -1
  140. package/dist/ui-ai-kit/p-56163e8c.entry.js +0 -1
  141. package/dist/ui-ai-kit/p-6d21d0fd.entry.js +0 -1
  142. package/dist/ui-ai-kit/p-6ddcd77b.entry.js +0 -1
  143. package/dist/ui-ai-kit/p-7hrZ8FOQ.js +0 -2
  144. package/dist/ui-ai-kit/p-8e90143e.entry.js +0 -1
  145. package/dist/ui-ai-kit/p-9938c277.entry.js +0 -1
  146. package/dist/ui-ai-kit/p-dc5b4a7f.entry.js +0 -1
  147. package/dist/ui-ai-kit/p-fb1702de.entry.js +0 -1
@@ -1,6 +1,6 @@
1
- import { r as registerInstance, c as createEvent, h, H as Host } from './index-7hrZ8FOQ.js';
1
+ import { r as registerInstance, c as createEvent, a as getElement, h, H as Host } from './index-B0yIzgh4.js';
2
2
 
3
- const aiVoiceInputCss = () => `:host{display:block;width:100%;font-family:var(--ai-font-family, "PingARLT", sans-serif);--ai-input-bg:var(--ai-bg-input, #ffffff);--ai-input-border-color:var(--ai-border-default, #eeeeee);--ai-send-button-bg:var(--ai-border-default, #eeeeee);--ai-send-button-border:var(--ai-border-default, #eeeeee);--ai-send-button-color:var(--ai-text-secondary, #737373);--ai-send-button-active-color:var(--ai-text-primary, #333333);--ai-voice-timer-color:var(--ai-text-secondary, #737373)}.wrapper{position:relative;padding:var(--ai-input-wrapper-padding, 16px)}.glow{position:absolute;bottom:20px;left:39px;right:39px;height:29px;border-radius:9999px;background:var(--ai-input-glow);filter:blur(20px);opacity:0.9;pointer-events:none}.input-container{position:relative;background-color:var(--ai-input-bg, #ffffff);border-radius:var(--ai-input-border-radius, 9999px);border:1px solid var(--ai-input-border-color, #eeeeee);box-shadow:0 1px 2px 0 var(--ai-input-shadow-color, rgba(18, 18, 23, 0.05));padding:var(--ai-input-padding, 12px);overflow:hidden}.recording-row{display:flex;align-items:center;gap:var(--ai-input-gap, 10px)}.cancel-button{display:inline-flex;align-items:center;justify-content:center;gap:4px;min-height:32px;max-height:32px;padding:4px 8px;border-radius:32px;border:2px solid var(--ai-send-button-border, var(--ai-border-default));background-color:var(--ai-send-button-bg, var(--ai-border-default));color:var(--ai-send-button-color, var(--ai-text-secondary));cursor:pointer;flex-shrink:0;transition:background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease}.cancel-button:hover{background-color:var(--ai-bg-surface);border-color:var(--ai-bg-surface)}.submit-button{display:inline-flex;align-items:center;justify-content:center;height:32px;width:32px;min-width:32px;padding:4px 8px;border-radius:32px;border:2px solid var(--ai-send-button-active-border, var(--ai-accent));background-color:var(--ai-send-button-active-bg, var(--ai-accent));color:var(--ai-accent-text);cursor:pointer;flex-shrink:0;transition:background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease}.submit-button:hover{background-color:var(--ai-send-button-active-hover-bg, var(--ai-accent));border-color:var(--ai-send-button-active-hover-border, var(--ai-accent))}.timer{font-size:13px;font-weight:500;font-family:var(--ai-font-family, "PingARLT", sans-serif);color:var(--ai-voice-timer-color, #737373);min-width:36px;text-align:center;flex-shrink:0}.timer.warning{color:var(--ai-voice-timer-warning-color, var(--ai-danger-text))}.waveform{flex:1;height:32px;max-width:100%}.error-message{position:absolute;bottom:-40px;left:50%;transform:translateX(-50%);background:var(--ai-voice-error-bg, var(--ai-danger-bg));color:var(--ai-voice-error-color, var(--ai-danger-text));font-size:11px;padding:6px 12px;border-radius:6px;white-space:nowrap;box-shadow:0 2px 8px rgba(0, 0, 0, 0.15);border:1px solid var(--ai-voice-error-border, var(--ai-danger-border));z-index:10}`;
3
+ const aiVoiceInputCss = () => `:host{display:block;width:100%}.wrapper{position:relative;padding:var(--Spacing-Sizes-lg, 12px)}.glow{position:absolute;bottom:20px;left:39px;right:39px;height:29px;border-radius:9999px;background:var(--ai-input-glow);filter:blur(20px);opacity:0;pointer-events:none;transition:opacity 0.2s ease}.glow.visible{opacity:0.9}.input-container{position:relative;background-color:var(--ai-bg-input);border-radius:var(--ai-input-border-radius, 9999px);border:1px solid var(--ai-border-default);box-shadow:var(--ai-shadow-sm);padding:var(--ai-input-padding, 12px);overflow:hidden}.recording-row{display:flex;align-items:center;gap:var(--ai-input-gap, 10px)}.cancel-button{display:inline-flex;align-items:center;justify-content:center;gap:4px;min-height:32px;max-height:32px;padding:4px 8px;border-radius:32px;border:2px solid var(--ai-border-default);background-color:var(--ai-border-default);color:var(--ai-text-secondary);cursor:pointer;flex-shrink:0;transition:background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease}.cancel-button:hover{background-color:var(--ai-bg-surface);border-color:var(--ai-bg-surface)}.submit-button{display:inline-flex;align-items:center;justify-content:center;height:32px;width:32px;min-width:32px;padding:4px 8px;border-radius:32px;border:2px solid var(--ai-send-button-active-border, var(--ai-accent));background-color:var(--ai-send-button-active-bg, var(--ai-accent));color:var(--ai-accent-text);cursor:pointer;flex-shrink:0;transition:background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease}.submit-button:hover{background-color:var(--ai-send-button-active-hover-bg, var(--ai-accent));border-color:var(--ai-send-button-active-hover-border, var(--ai-accent))}@keyframes pulse-once{0%{transform:scale(1)}40%{transform:scale(1.18)}100%{transform:scale(1)}}.submit-button.pulse{animation:pulse-once 0.35s ease}.timer{font-size:13px;font-weight:500;color:var(--ai-text-secondary);min-width:36px;text-align:center;flex-shrink:0}.timer.warning{color:var(--ai-voice-timer-warning-color, var(--ai-danger-text))}.waveform{flex:1;min-width:0;height:32px}.error-message{position:absolute;bottom:-40px;left:50%;transform:translateX(-50%);background:var(--ai-voice-error-bg, var(--ai-danger-bg));color:var(--ai-voice-error-color, var(--ai-danger-text));font-size:11px;padding:6px 12px;border-radius:6px;white-space:nowrap;box-shadow:var(--ai-shadow-error);border:1px solid var(--ai-voice-error-border, var(--ai-danger-border));z-index:10}`;
4
4
 
5
5
  const MAX_RECORDING_TIME = 60; // seconds
6
6
  const VoiceInput = class {
@@ -9,16 +9,22 @@ const VoiceInput = class {
9
9
  this.audioRecorded = createEvent(this, "audioRecorded");
10
10
  this.recordingCancel = createEvent(this, "recordingCancel");
11
11
  }
12
+ get el() { return getElement(this); }
12
13
  /** Whether the voice input is disabled */
13
14
  disabled = false;
14
15
  /** Whether to show the waveform animation */
15
16
  showWaveform = true;
16
17
  /** Whether to auto-start recording on mount */
17
18
  autoStart = false;
19
+ /** Error text to display on mic access failure. Defaults to Arabic; falls back to English when document lang is 'en' */
20
+ errorText = '';
21
+ /** Waveform bar color. Falls back to --ai-waveform-color CSS var, then #9ca3af */
22
+ waveformColor = '';
18
23
  /** Internal state */
19
24
  state = 'idle';
20
25
  error = null;
21
26
  recordingDuration = 0;
27
+ submitPulse = false;
22
28
  /** Event emitted when audio blob is ready */
23
29
  audioRecorded;
24
30
  /** Event emitted when recording is canceled */
@@ -36,7 +42,7 @@ const VoiceInput = class {
36
42
  animationFrameId = 0;
37
43
  prevHeights = [];
38
44
  componentDidLoad() {
39
- if (this.autoStart) {
45
+ if (this.autoStart && !this.disabled) {
40
46
  this.startRecording();
41
47
  }
42
48
  }
@@ -72,6 +78,11 @@ const VoiceInput = class {
72
78
  this.streamRef = null;
73
79
  }
74
80
  };
81
+ getErrorText() {
82
+ if (this.errorText)
83
+ return this.errorText;
84
+ return document.documentElement.lang === 'en' ? 'Microphone access denied' : 'تعذّر الوصول للميكروفون';
85
+ }
75
86
  startRecording = async () => {
76
87
  try {
77
88
  this.error = null;
@@ -110,10 +121,10 @@ const VoiceInput = class {
110
121
  this.drawWaveform();
111
122
  });
112
123
  }
113
- // Start timer
124
+ // Start timer — 1 s interval avoids unnecessary re-renders
114
125
  this.recordingTimer = window.setInterval(() => {
115
126
  this.recordingDuration = Math.floor((Date.now() - this.recordingStartTime) / 1000);
116
- }, 100);
127
+ }, 1000);
117
128
  // Auto-stop after max time
118
129
  this.maxTimeoutRef = window.setTimeout(() => {
119
130
  this.stopRecording();
@@ -121,27 +132,41 @@ const VoiceInput = class {
121
132
  }
122
133
  catch (err) {
123
134
  console.error('Error starting recording:', err);
124
- this.error = 'Microphone access denied';
135
+ this.error = this.getErrorText();
125
136
  this.state = 'idle';
126
137
  }
127
138
  };
128
139
  setupMediaRecorder = (stream) => {
129
- const mediaRecorder = new MediaRecorder(stream, {
130
- mimeType: 'audio/webm',
131
- });
140
+ // Pick a supported MIME type — audio/webm is unavailable on iOS/Safari
141
+ const mimeType = MediaRecorder.isTypeSupported('audio/webm')
142
+ ? 'audio/webm'
143
+ : MediaRecorder.isTypeSupported('audio/ogg')
144
+ ? 'audio/ogg'
145
+ : '';
146
+ const options = mimeType ? { mimeType } : {};
147
+ const mediaRecorder = new MediaRecorder(stream, options);
132
148
  mediaRecorder.ondataavailable = e => {
133
149
  if (e.data.size > 0) {
134
150
  this.audioChunks.push(e.data);
135
151
  }
136
152
  };
137
153
  mediaRecorder.onstop = () => {
138
- const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm' });
154
+ const blobType = mimeType || 'audio/mp4';
155
+ const audioBlob = new Blob(this.audioChunks, { type: blobType });
139
156
  this.audioRecorded.emit({ blob: audioBlob, duration: this.recordingDuration });
140
157
  };
141
158
  this.mediaRecorderRef = mediaRecorder;
142
159
  mediaRecorder.start(100); // Collect data every 100ms
143
160
  };
144
161
  stopRecording = () => {
162
+ // Guard: require at least 1 second of audio
163
+ if (this.recordingDuration < 1) {
164
+ this.submitPulse = true;
165
+ setTimeout(() => {
166
+ this.submitPulse = false;
167
+ }, 400);
168
+ return;
169
+ }
145
170
  if (this.recordingTimer) {
146
171
  clearInterval(this.recordingTimer);
147
172
  this.recordingTimer = null;
@@ -171,21 +196,51 @@ const VoiceInput = class {
171
196
  const ctx = canvas.getContext('2d');
172
197
  if (!ctx)
173
198
  return;
174
- const barCount = 100;
175
199
  const barWidth = 1;
176
200
  const gap = 2;
201
+ const minHeight = 4;
177
202
  const bufferLength = this.analyserRef.frequencyBinCount;
178
203
  const dataArray = new Uint8Array(bufferLength);
179
- const binsPerBar = Math.max(1, Math.floor(bufferLength / barCount));
180
- const minHeight = 4;
181
- // Initialize lerp state
182
- if (this.prevHeights.length !== barCount) {
183
- this.prevHeights = new Array(barCount).fill(minHeight);
184
- }
204
+ // Resolve waveform color from prop → CSS var → fallback
205
+ const resolvedColor = this.waveformColor ||
206
+ getComputedStyle(this.el).getPropertyValue('--ai-waveform-color').trim() ||
207
+ '#9ca3af';
208
+ const drawRoundRect = (x, y, w, h, r) => {
209
+ ctx.beginPath();
210
+ if (typeof ctx.roundRect === 'function') {
211
+ ctx.roundRect(x, y, w, h, r);
212
+ }
213
+ else {
214
+ // arc-based fallback for Safari < 15.4
215
+ const cr = Math.min(r, w / 2, h / 2);
216
+ ctx.moveTo(x + cr, y);
217
+ ctx.lineTo(x + w - cr, y);
218
+ ctx.arcTo(x + w, y, x + w, y + cr, cr);
219
+ ctx.lineTo(x + w, y + h - cr);
220
+ ctx.arcTo(x + w, y + h, x + w - cr, y + h, cr);
221
+ ctx.lineTo(x + cr, y + h);
222
+ ctx.arcTo(x, y + h, x, y + h - cr, cr);
223
+ ctx.lineTo(x, y + cr);
224
+ ctx.arcTo(x, y, x + cr, y, cr);
225
+ ctx.closePath();
226
+ }
227
+ };
185
228
  const draw = () => {
186
229
  if (this.state !== 'recording')
187
230
  return;
188
231
  this.animationFrameId = requestAnimationFrame(draw);
232
+ // Sync canvas buffer to actual rendered size so it never overflows
233
+ const renderedWidth = canvas.offsetWidth;
234
+ if (renderedWidth > 0 && canvas.width !== renderedWidth) {
235
+ canvas.width = renderedWidth;
236
+ }
237
+ // Recompute barCount each frame based on actual canvas width
238
+ const barCount = Math.min(100, Math.floor(canvas.width / (barWidth + gap)));
239
+ const binsPerBar = Math.max(1, Math.floor(bufferLength / barCount));
240
+ // Re-initialize lerp state when barCount changes
241
+ if (this.prevHeights.length !== barCount) {
242
+ this.prevHeights = new Array(barCount).fill(minHeight);
243
+ }
189
244
  this.analyserRef.getByteFrequencyData(dataArray);
190
245
  ctx.clearRect(0, 0, canvas.width, canvas.height);
191
246
  const centerY = canvas.height / 2;
@@ -208,9 +263,8 @@ const VoiceInput = class {
208
263
  const barHeight = this.prevHeights[i];
209
264
  const x = startX + i * (barWidth + gap);
210
265
  const y = centerY - barHeight / 2;
211
- ctx.fillStyle = '#9ca3af';
212
- ctx.beginPath();
213
- ctx.roundRect(x, y, barWidth, barHeight, barWidth / 2);
266
+ ctx.fillStyle = resolvedColor;
267
+ drawRoundRect(x, y, barWidth, barHeight, barWidth / 2);
214
268
  ctx.fill();
215
269
  }
216
270
  };
@@ -223,7 +277,7 @@ const VoiceInput = class {
223
277
  };
224
278
  render() {
225
279
  const remaining = MAX_RECORDING_TIME - this.recordingDuration;
226
- return (h(Host, { key: 'c8bfc86b0c3951460ec23b66e6e018d25c8fa950' }, h("div", { key: '114eae0be8e5ebcbda11cdff7fd0714221c0e27a', class: "wrapper" }, this.state === 'recording' && h("div", { key: '203008d77352bd2fda62a2f7728f061ea4b1ea4f', class: "glow", "aria-hidden": "true" }), h("div", { key: 'a92db7f67500d731faca57e1634aec4a383a9ab7', class: "input-container" }, this.state === 'idle' ? (h("div", { class: "recording-row" }, h("button", { type: "button", class: "submit-button", onClick: this.startRecording, disabled: this.disabled, "aria-label": "Start recording" }, h("ai-icon", { name: "mic", size: 16 })), this.error && (h("div", { class: "error-message", role: "alert" }, this.error)))) : (h("div", { class: "recording-row" }, h("button", { type: "button", class: "cancel-button", onClick: this.cancelRecording, "aria-label": "Cancel" }, h("ai-icon", { name: "cancel", size: 14 })), h("div", { class: `timer${remaining <= 5 ? ' warning' : ''}` }, this.formatDuration(this.recordingDuration)), this.showWaveform && h("canvas", { ref: el => (this.canvasRef = el), class: "waveform", width: "260", height: "32" }), h("button", { type: "button", class: "submit-button", onClick: this.stopRecording, "aria-label": "Send" }, h("ai-icon", { name: "arrow-up", size: 14 }))))))));
280
+ return (h(Host, { key: '225036c9c966084bcbdef9760d08cb677c985cc1' }, h("div", { key: '3cb3841dcb8a8e283cc325a200073ba3d540d7f8', class: "wrapper" }, h("div", { key: '1e71acf6ceb25d50d4131bf1a8021837756d0a41', class: `glow${this.state === 'recording' ? ' visible' : ''}`, "aria-hidden": "true" }), h("div", { key: 'c96027342fdf08edc990cae9f25ebb087dd33612', class: "input-container" }, this.state === 'idle' ? (h("div", { class: "recording-row" }, h("button", { type: "button", class: "submit-button", onClick: this.startRecording, disabled: this.disabled, "aria-label": "Start recording" }, h("ai-icon", { name: "mic", size: 16 })), this.error && (h("div", { class: "error-message", role: "alert" }, this.error)))) : (h("div", { class: "recording-row" }, h("button", { type: "button", class: "cancel-button", onClick: this.cancelRecording, "aria-label": "Cancel" }, h("ai-icon", { name: "cancel", size: 14 })), h("div", { class: `timer${remaining <= 5 ? ' warning' : ''}` }, this.formatDuration(this.recordingDuration)), this.showWaveform && h("canvas", { ref: el => (this.canvasRef = el), class: "waveform", height: "32" }), h("button", { type: "button", class: `submit-button${this.submitPulse ? ' pulse' : ''}`, onClick: this.stopRecording, "aria-label": "Send" }, h("ai-icon", { name: "arrow-up", size: 14 }))))))));
227
281
  }
228
282
  };
229
283
  VoiceInput.style = aiVoiceInputCss();
@@ -75,6 +75,30 @@ const iconRegistry = {
75
75
  viewBox: '0 0 24 24',
76
76
  content: ` <path d="M15.1667 0.999756L15.7646 2.11753C16.1689 2.87322 16.371 3.25107 16.2374 3.41289C16.1037 3.57471 15.6635 3.44402 14.7831 3.18264C13.9029 2.92131 12.9684 2.78071 12 2.78071C6.75329 2.78071 2.5 6.90822 2.5 11.9998C2.5 13.6789 2.96262 15.2533 3.77093 16.6093M8.83333 22.9998L8.23536 21.882C7.83108 21.1263 7.62894 20.7484 7.7626 20.5866C7.89627 20.4248 8.33649 20.5555 9.21689 20.8169C10.0971 21.0782 11.0316 21.2188 12 21.2188C17.2467 21.2188 21.5 17.0913 21.5 11.9998C21.5 10.3206 21.0374 8.74623 20.2291 7.39023" stroke="currentColor" />`,
77
77
  },
78
+ 'list': {
79
+ viewBox: '0 0 24 24',
80
+ content: '<path d="M8 6h13M8 12h13M8 18h13" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/><path d="M3 6h.01M3 12h.01M3 18h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/>',
81
+ },
82
+ 'route': {
83
+ viewBox: '0 0 24 24',
84
+ content: '<circle cx="6" cy="19" r="2" stroke="currentColor" stroke-width="2" fill="none"/><circle cx="18" cy="5" r="2" stroke="currentColor" stroke-width="2" fill="none"/><path d="M6 17V11a6 6 0 0 1 6-6h2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M15 8l3-3-3-3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
85
+ },
86
+ 'check-circle': {
87
+ viewBox: '0 0 24 24',
88
+ content: '<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2" fill="none"/><path d="M8 12l3 3 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
89
+ },
90
+ 'wifi-off': {
91
+ viewBox: '0 0 24 24',
92
+ content: '<path d="M1 1l22 22M16.72 11.06A11 11 0 0 0 12 10c-2.06 0-3.96.57-5.59 1.56M5 12.55a11 11 0 0 0-1.48 1.45M10.71 5.05A16 16 0 0 1 22.56 9M1.42 9a15.91 15.91 0 0 1 4.7-2.88M8.53 16.11a6 6 0 0 1 6.95 0M12 20h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>',
93
+ },
94
+ 'warning': {
95
+ viewBox: '0 0 24 24',
96
+ content: '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/><path d="M12 9v4M12 17h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/>',
97
+ },
98
+ 'ellipsis': {
99
+ viewBox: '0 0 24 24',
100
+ content: '<circle cx="5" cy="12" r="2" fill="currentColor"/><circle cx="12" cy="12" r="2" fill="currentColor"/><circle cx="19" cy="12" r="2" fill="currentColor"/>',
101
+ },
78
102
  };
79
103
 
80
104
  export { iconRegistry as i };
@@ -2,7 +2,7 @@ const NAMESPACE = 'ui-ai-kit';
2
2
  const BUILD = /* ui-ai-kit */ { hotModuleReplacement: false, hydratedSelectorName: "hydrated", lazyLoad: true, propChangeCallback: true, state: true, updatable: true};
3
3
 
4
4
  const globalScripts = () => {};
5
- const globalStyles = "@import url(\"https://cdn.salla.network/fonts/pingarlt.css\");:root{--ai-font-family:\"PingARLT\", sans-serif;font-family:var(--ai-font-family);--ai-bg-card:hsl(var(--white));--ai-bg-surface:hsl(var(--gray-300));--ai-bg-input:hsl(var(--white));--ai-text-primary:hsl(var(--dark));--ai-text-secondary:hsl(var(--dark-100));--ai-text-muted:hsl(var(--gray));--ai-border-default:hsl(var(--gray-400));--ai-border-light:hsl(var(--gray-300));--ai-accent:hsl(var(--secondary));--ai-accent-dark:hsl(var(--primary));--ai-accent-text:hsl(var(--dark));--ai-user-bubble-bg:hsl(var(--gray-300));--ai-agent-bubble-bg:hsl(var(--white));--ai-warning-bg:hsl(var(--warning-100));--ai-warning-border:hsl(var(--warning));--ai-success:hsl(var(--success));--ai-success-text:hsl(var(--success));--ai-success-bg:hsl(var(--success-100));--ai-danger-text:hsl(var(--danger));--ai-danger-bg:hsl(var(--danger-100));--ai-danger-border:hsl(var(--danger-200));--ai-accent-bg:hsl(var(--secondary-100));--ai-focus-ring:hsl(var(--info));--ai-amber:hsl(var(--warning));--ai-scrollbar-thumb:rgba(0, 0, 0, 0.15);--ai-glow-gradient:linear-gradient(90deg, hsl(var(--dark-100)) 0%, hsl(var(--gray)) 50%, hsl(var(--dark-100)) 100%);--ai-input-glow:linear-gradient(to right, hsl(var(--secondary-400)), hsl(var(--secondary-100)) 10%, hsl(var(--secondary)))}.dark{--ai-bg-card:hsl(var(--gray-100));--ai-bg-surface:hsl(var(--white-300));--ai-bg-input:hsl(var(--gray-100));--ai-text-primary:hsl(var(--dark));--ai-text-secondary:hsl(var(--dark-200));--ai-text-muted:hsl(var(--gray));--ai-border-default:hsl(var(--gray-400));--ai-border-light:hsl(var(--gray-300));--ai-accent:hsl(var(--secondary));--ai-accent-dark:hsl(var(--primary-500));--ai-accent-text:hsl(var(--primary-force));--ai-user-bubble-bg:hsl(var(--gray-400));--ai-agent-bubble-bg:hsl(var(--gray-100));--ai-warning-bg:hsl(var(--warning-100));--ai-warning-border:hsl(var(--warning));--ai-success:hsl(var(--success));--ai-success-text:hsl(var(--success));--ai-success-bg:hsl(var(--success-100));--ai-danger-text:hsl(var(--danger));--ai-danger-bg:hsl(var(--danger-100));--ai-danger-border:hsl(var(--danger-200));--ai-accent-bg:hsl(var(--secondary-100));--ai-focus-ring:hsl(var(--info));--ai-amber:hsl(var(--warning));--ai-scrollbar-thumb:rgba(255, 255, 255, 0.2);--ai-glow-gradient:linear-gradient(90deg, hsl(var(--gray)) 0%, hsl(var(--dark-300)) 50%, hsl(var(--gray)) 100%);--ai-input-glow:linear-gradient(to right, hsl(var(--secondary-400)), hsl(var(--secondary-100)) 10%, hsl(var(--secondary)))}";
5
+ const globalStyles = "@import url(\"https://cdn.salla.network/fonts/pingarlt.css\");:root{--ai-font-family:\"PingARLT\", sans-serif;font-family:var(--ai-font-family);--ai-bg-card:hsl(var(--white));--ai-bg-surface:hsl(var(--gray-300));--ai-bg-input:hsl(var(--white));--ai-text-primary:hsl(var(--dark));--ai-text-secondary:hsl(var(--dark-100));--ai-text-muted:hsl(var(--gray));--ai-border-default:hsl(var(--gray-400));--ai-border-light:hsl(var(--gray-300));--ai-accent:hsl(var(--secondary));--ai-accent-dark:hsl(var(--primary));--ai-accent-text:hsl(var(--dark));--ai-user-bubble-bg:hsl(var(--gray-300));--ai-agent-bubble-bg:hsl(var(--white));--ai-warning-bg:hsl(var(--warning-100));--ai-warning-border:hsl(var(--warning));--ai-success:hsl(var(--success));--ai-success-text:hsl(var(--success));--ai-success-bg:hsl(var(--success-100));--ai-danger-text:hsl(var(--danger));--ai-danger-bg:hsl(var(--danger-100));--ai-danger-border:hsl(var(--danger-200));--ai-accent-bg:hsl(var(--secondary-100));--ai-focus-ring:hsl(var(--info));--ai-amber:hsl(var(--warning));--ai-scrollbar-thumb:rgba(0, 0, 0, 0.15);--ai-scrollbar-thumb-hover:rgba(0, 0, 0, 0.28);--ai-glow-gradient:linear-gradient(90deg, hsl(var(--dark-100)) 0%, hsl(var(--gray)) 50%, hsl(var(--dark-100)) 100%);--ai-input-glow:linear-gradient(90deg, #73F0EE 0%, #EBF1B1 10%, #A4FFE5 100%);--ai-shadow-sm:0px 1px 2px 0px hsl(var(--dark) / 0.05);--ai-shadow-inner:inset 0px 0px 3px 1px hsl(var(--dark) / 0.06);--ai-shadow-badge:0px 0px 2px 1px hsl(var(--dark) / 0.08);--ai-shadow-active:0px 4px 6px -1px hsl(var(--dark) / 0.08), 0px 2px 4px -1px hsl(var(--dark) / 0.06);--ai-shadow-float:0 8px 32px hsl(var(--dark) / 0.12), 0 2px 8px hsl(var(--dark) / 0.08);--ai-shadow-error:0 2px 8px hsl(var(--dark) / 0.15);--ai-shadow-watermark:drop-shadow(0 4px 6px hsl(var(--dark) / 0.05));--ai-hover-overlay:rgba(0, 0, 0, 0.06);--ai-input-focus-glow:0 0 10px 4px hsl(var(--secondary) / 0.4);--ai-font-family-mono:monospace;--ai-spacing-2xl:var(--Spacing-Sizes-2xl, 16px)}.dark{--ai-bg-card:hsl(var(--gray-100));--ai-bg-surface:hsl(var(--white-300));--ai-bg-input:hsl(var(--gray-100));--ai-text-primary:hsl(var(--dark));--ai-text-secondary:hsl(var(--dark-200));--ai-text-muted:hsl(var(--gray));--ai-border-default:hsl(var(--gray-400));--ai-border-light:hsl(var(--gray-300));--ai-accent:hsl(var(--secondary));--ai-accent-dark:hsl(var(--primary-500));--ai-accent-text:hsl(var(--primary-force));--ai-user-bubble-bg:hsl(var(--gray-400));--ai-agent-bubble-bg:hsl(var(--gray-100));--ai-warning-bg:hsl(var(--warning-100));--ai-warning-border:hsl(var(--warning));--ai-success:hsl(var(--success));--ai-success-text:hsl(var(--success));--ai-success-bg:hsl(var(--success-100));--ai-danger-text:hsl(var(--danger));--ai-danger-bg:hsl(var(--danger-100));--ai-danger-border:hsl(var(--danger-200));--ai-accent-bg:hsl(var(--secondary-100));--ai-focus-ring:hsl(var(--info));--ai-amber:hsl(var(--warning));--ai-scrollbar-thumb:rgba(255, 255, 255, 0.2);--ai-scrollbar-thumb-hover:rgba(255, 255, 255, 0.35);--ai-hover-overlay:rgba(255, 255, 255, 0.08);--ai-glow-gradient:linear-gradient(90deg, hsl(var(--gray)) 0%, hsl(var(--dark-300)) 50%, hsl(var(--gray)) 100%);--ai-input-glow:linear-gradient(to right, hsl(var(--secondary-400)), hsl(var(--secondary-100)) 10%, hsl(var(--secondary)))}";
6
6
 
7
7
  /*
8
8
  Stencil Client Platform v4.43.2 | MIT Licensed | https://stenciljs.com
@@ -1,10 +1,10 @@
1
- import { g as globalScripts, b as bootstrapLazy } from './index-7hrZ8FOQ.js';
2
- export { s as setNonce } from './index-7hrZ8FOQ.js';
1
+ import { g as globalScripts, b as bootstrapLazy } from './index-B0yIzgh4.js';
2
+ export { s as setNonce } from './index-B0yIzgh4.js';
3
3
 
4
4
  const defineCustomElements = async (win, options) => {
5
5
  if (typeof window === 'undefined') return undefined;
6
6
  await globalScripts();
7
- return bootstrapLazy([["ai-chat-container",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"isMobile":[32]},null,{"position":[{"positionChanged":0}]}]]],["ai-message-input",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"inputValue":[32],"setInputValue":[64]}]]],["ai-voice-input",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"state":[32],"error":[32],"recordingDuration":[32]}]]],["ai-card",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"]}]]],["ai-chat-message",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-link",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"steps":[1],"headerTitle":[1,"header-title"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-suggestion",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon",[[513,"ai-icon",{"name":[1],"size":[2]}]]]], options);
7
+ return bootstrapLazy([["ai-message-input",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"maxLength":[2,"max-length"],"isRecording":[4,"is-recording"],"inputValue":[32],"showVoiceRecorder":[32],"isMultiline":[32],"setInputValue":[64]},null,{"isRecording":[{"onIsRecordingChange":0}]}]]],["ai-chat-container",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"theme":[1],"isMobile":[32],"floatLeft":[32],"floatTop":[32],"scrollToBottom":[64]},null,{"isOpen":[{"isOpenChanged":0}],"position":[{"positionChanged":0}]}]]],["ai-card",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"],"statusIndicator":[1,"status-indicator"],"avatarError":[32]}]]],["ai-chat-message",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-conversation-list",[[513,"ai-conversation-list",{"items":[1],"activeId":[1,"active-id"],"loading":[4]}]]],["ai-conversation-summary",[[769,"ai-conversation-summary",{"conversation":[1],"summary":[1],"messageCount":[2,"message-count"],"language":[1]}]]],["ai-link",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"thinkingSubtext":[1,"thinking-subtext"],"steps":[16],"headerTitle":[1,"header-title"],"currentAgent":[1,"current-agent"],"showAgentBadges":[4,"show-agent-badges"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-route-decision",[[513,"ai-route-decision",{"selectedAgent":[1,"selected-agent"],"agentIcon":[1,"agent-icon"],"reason":[1],"confidence":[2],"detectedLanguage":[1,"detected-language"],"expanded":[1028],"_expanded":[32]}]]],["ai-suggestion",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon",[[513,"ai-icon",{"name":[1],"size":[2]}]]],["ai-voice-input",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"errorText":[1,"error-text"],"waveformColor":[1,"waveform-color"],"state":[32],"error":[32],"recordingDuration":[32],"submitPulse":[32]}]]]], options);
8
8
  };
9
9
 
10
10
  export { defineCustomElements };
@@ -1,5 +1,5 @@
1
- import { p as promiseResolve, g as globalScripts, b as bootstrapLazy } from './index-7hrZ8FOQ.js';
2
- export { s as setNonce } from './index-7hrZ8FOQ.js';
1
+ import { p as promiseResolve, g as globalScripts, b as bootstrapLazy } from './index-B0yIzgh4.js';
2
+ export { s as setNonce } from './index-B0yIzgh4.js';
3
3
 
4
4
  /*
5
5
  Stencil Client Patch Browser v4.43.2 | MIT Licensed | https://stenciljs.com
@@ -16,5 +16,5 @@ var patchBrowser = () => {
16
16
 
17
17
  patchBrowser().then(async (options) => {
18
18
  await globalScripts();
19
- return bootstrapLazy([["ai-chat-container",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"isMobile":[32]},null,{"position":[{"positionChanged":0}]}]]],["ai-message-input",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"inputValue":[32],"setInputValue":[64]}]]],["ai-voice-input",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"state":[32],"error":[32],"recordingDuration":[32]}]]],["ai-card",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"]}]]],["ai-chat-message",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-link",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"steps":[1],"headerTitle":[1,"header-title"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-suggestion",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon",[[513,"ai-icon",{"name":[1],"size":[2]}]]]], options);
19
+ return bootstrapLazy([["ai-message-input",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"maxLength":[2,"max-length"],"isRecording":[4,"is-recording"],"inputValue":[32],"showVoiceRecorder":[32],"isMultiline":[32],"setInputValue":[64]},null,{"isRecording":[{"onIsRecordingChange":0}]}]]],["ai-chat-container",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"theme":[1],"isMobile":[32],"floatLeft":[32],"floatTop":[32],"scrollToBottom":[64]},null,{"isOpen":[{"isOpenChanged":0}],"position":[{"positionChanged":0}]}]]],["ai-card",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"],"statusIndicator":[1,"status-indicator"],"avatarError":[32]}]]],["ai-chat-message",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-conversation-list",[[513,"ai-conversation-list",{"items":[1],"activeId":[1,"active-id"],"loading":[4]}]]],["ai-conversation-summary",[[769,"ai-conversation-summary",{"conversation":[1],"summary":[1],"messageCount":[2,"message-count"],"language":[1]}]]],["ai-link",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"thinkingSubtext":[1,"thinking-subtext"],"steps":[16],"headerTitle":[1,"header-title"],"currentAgent":[1,"current-agent"],"showAgentBadges":[4,"show-agent-badges"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-route-decision",[[513,"ai-route-decision",{"selectedAgent":[1,"selected-agent"],"agentIcon":[1,"agent-icon"],"reason":[1],"confidence":[2],"detectedLanguage":[1,"detected-language"],"expanded":[1028],"_expanded":[32]}]]],["ai-suggestion",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon",[[513,"ai-icon",{"name":[1],"size":[2]}]]],["ai-voice-input",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"errorText":[1,"error-text"],"waveformColor":[1,"waveform-color"],"state":[32],"error":[32],"recordingDuration":[32],"submitPulse":[32]}]]]], options);
20
20
  });
@@ -12,17 +12,27 @@ export declare class ChatContainer {
12
12
  showWatermark: boolean;
13
13
  /** Height of the panel when position='float' */
14
14
  floatHeight: string;
15
+ /** Color theme for the panel */
16
+ theme: 'light' | 'dark' | 'auto';
15
17
  isMobile: boolean;
18
+ floatLeft: string;
19
+ floatTop: string;
16
20
  private containerRef;
21
+ private messagesAreaRef;
17
22
  private dragState;
18
- private resizeObserver;
23
+ private dragListener;
24
+ constructor();
19
25
  componentWillLoad(): void;
20
26
  componentDidLoad(): void;
27
+ isOpenChanged(newVal: boolean): void;
21
28
  positionChanged(newVal: string): void;
22
29
  disconnectedCallback(): void;
30
+ /** Programmatically scroll the messages area to the bottom */
31
+ scrollToBottom(): Promise<void>;
23
32
  private checkMobile;
24
33
  private setupDrag;
25
34
  private getContainerClasses;
26
35
  private getContainerStyle;
36
+ private isDark;
27
37
  render(): any;
28
38
  }
@@ -13,14 +13,17 @@ export declare class AiChatHeader {
13
13
  /** Human mode: show the back button */
14
14
  showBack: boolean;
15
15
  isDraggable: boolean;
16
+ /** Human mode: status indicator variant */
17
+ statusIndicator: 'online' | 'offline' | 'busy' | 'away';
18
+ private avatarError;
16
19
  /** Cancel / close button */
17
20
  closeClick: EventEmitter<void>;
18
21
  /** Pencil-edit button (agent mode) */
19
22
  editClick: EventEmitter<void>;
20
23
  /** Title / chevron click → open conversation list (agent mode) */
21
24
  dropdownClick: EventEmitter<void>;
22
- /** Chevron-down button (human mode) */
23
- moreClick: EventEmitter<void>;
25
+ /** More options button */
26
+ positionClick: EventEmitter<void>;
24
27
  /** Back-arrow button (human mode) */
25
28
  backClick: EventEmitter<void>;
26
29
  /**
@@ -32,6 +35,8 @@ export declare class AiChatHeader {
32
35
  clientY: number;
33
36
  }>;
34
37
  private renderIcon;
38
+ private renderAvatar;
39
+ private renderDragBtn;
35
40
  private renderAgentMode;
36
41
  private renderHumanMode;
37
42
  render(): any;
@@ -0,0 +1,24 @@
1
+ import { EventEmitter } from '../../stencil-public-runtime';
2
+ export interface ConversationItem {
3
+ id: string;
4
+ title: string;
5
+ preview: string;
6
+ timestamp: string;
7
+ rating?: 1 | 2 | 3 | 4 | 5 | null;
8
+ }
9
+ export declare class AiConversationList {
10
+ /** JSON array of ConversationItem */
11
+ items: string;
12
+ /** ID of the currently active conversation */
13
+ activeId: string;
14
+ /** Show skeleton loading state */
15
+ loading: boolean;
16
+ conversationSelect: EventEmitter<string>;
17
+ conversationDelete: EventEmitter<string>;
18
+ private renderIcon;
19
+ private getItems;
20
+ private formatRelativeTime;
21
+ private renderRatingDots;
22
+ private renderSkeleton;
23
+ render(): any;
24
+ }
@@ -0,0 +1,12 @@
1
+ export declare class AiConversationSummary {
2
+ /** Card heading */
3
+ conversation: string;
4
+ /** Summary body text */
5
+ summary: string;
6
+ /** Total message count shown as a badge */
7
+ messageCount: number;
8
+ /** Conversation language label */
9
+ language: string;
10
+ private renderIcon;
11
+ render(): any;
12
+ }
@@ -1,19 +1,25 @@
1
1
  import { EventEmitter } from '../../stencil-public-runtime';
2
2
  export interface LoadingStep {
3
- id: string;
4
- title: string;
5
- status: 'pending' | 'executing' | 'completed' | 'failed';
6
- agent?: string;
3
+ step: number;
4
+ action: string;
5
+ reason?: string;
6
+ status?: 'pending' | 'executing' | 'completed' | 'failed';
7
7
  }
8
8
  export declare class AiLoading {
9
9
  /** Main mode switch */
10
10
  mode: 'thinking' | 'steps';
11
11
  /** Thinking mode status text */
12
12
  statusText: string;
13
+ /** Secondary shimmer line in thinking mode (e.g. live node name) */
14
+ thinkingSubtext: string;
13
15
  /** Steps as JSON string array of LoadingStep */
14
- steps: string;
16
+ steps: LoadingStep[];
15
17
  /** Steps mode title */
16
18
  headerTitle: string;
19
+ /** Agent name shown in header alongside sparkle */
20
+ currentAgent: string;
21
+ /** Show per-step agent chips */
22
+ showAgentBadges: boolean;
17
23
  /** Steps mode expand state */
18
24
  expanded: boolean;
19
25
  /** Whether steps card is collapsible */
@@ -25,9 +31,9 @@ export declare class AiLoading {
25
31
  private renderIcon;
26
32
  private renderSparkleAvatar;
27
33
  private renderStepBadge;
28
- private getStepsList;
29
34
  private handleToggle;
30
35
  private renderThinkingMode;
36
+ private renderPlanningShimmer;
31
37
  private renderStepsMode;
32
38
  render(): any;
33
39
  }
@@ -7,16 +7,30 @@ export declare class MessageInput {
7
7
  disabled: boolean;
8
8
  /** Whether to show the voice recording button */
9
9
  showVoiceButton: boolean;
10
+ /** Maximum characters allowed */
11
+ maxLength: number;
12
+ /** External prop to show/hide the inline voice recorder */
13
+ isRecording: boolean;
10
14
  inputValue: string;
15
+ showVoiceRecorder: boolean;
16
+ isMultiline: boolean;
11
17
  private textareaRef;
12
18
  /** Event emitted when a message is sent */
13
19
  sendMessage: EventEmitter<string>;
14
- /** Event emitted when the voice button is clicked caller controls rendering the voice recorder */
15
- voiceButtonClick: EventEmitter<void>;
20
+ /** Event emitted when voice recording is complete and audio is ready */
21
+ voiceAudioReady: EventEmitter<{
22
+ blob: Blob;
23
+ duration: number;
24
+ }>;
25
+ onIsRecordingChange(newVal: boolean): void;
16
26
  /** Set the textarea value programmatically (e.g. after speech-to-text transcription) */
17
27
  setInputValue(value: string): Promise<void>;
28
+ private updateHeight;
18
29
  private handleSendMessage;
19
- private handleKeyPress;
30
+ private handleKeyDown;
31
+ private handleVoiceClick;
32
+ private handleAudioRecorded;
33
+ private handleRecordingCancel;
20
34
  private handleInputChange;
21
35
  render(): any;
22
36
  }
@@ -0,0 +1,21 @@
1
+ import { EventEmitter } from '../../stencil-public-runtime';
2
+ export declare class AiRouteDecision {
3
+ /** Selected agent name */
4
+ selectedAgent: string;
5
+ /** Agent icon — emoji or short text displayed before the agent name */
6
+ agentIcon: string;
7
+ /** Reason for routing decision (shown when expanded) */
8
+ reason: string;
9
+ /** Routing confidence percentage 0–100 */
10
+ confidence: number;
11
+ /** Detected language label (shown when expanded) */
12
+ detectedLanguage: string;
13
+ /** Initial expanded state */
14
+ expanded: boolean;
15
+ private _expanded;
16
+ routeExpand: EventEmitter<boolean>;
17
+ componentWillLoad(): void;
18
+ private renderIcon;
19
+ private handleToggle;
20
+ render(): any;
21
+ }
@@ -1,16 +1,22 @@
1
1
  import { EventEmitter } from '../../stencil-public-runtime';
2
2
  type RecordingState = 'idle' | 'recording';
3
3
  export declare class VoiceInput {
4
+ el: HTMLElement;
4
5
  /** Whether the voice input is disabled */
5
6
  disabled: boolean;
6
7
  /** Whether to show the waveform animation */
7
8
  showWaveform: boolean;
8
9
  /** Whether to auto-start recording on mount */
9
10
  autoStart: boolean;
11
+ /** Error text to display on mic access failure. Defaults to Arabic; falls back to English when document lang is 'en' */
12
+ errorText: string;
13
+ /** Waveform bar color. Falls back to --ai-waveform-color CSS var, then #9ca3af */
14
+ waveformColor: string;
10
15
  /** Internal state */
11
16
  state: RecordingState;
12
17
  error: string | null;
13
18
  recordingDuration: number;
19
+ submitPulse: boolean;
14
20
  /** Event emitted when audio blob is ready */
15
21
  audioRecorded: EventEmitter<{
16
22
  blob: Blob;
@@ -32,6 +38,7 @@ export declare class VoiceInput {
32
38
  componentDidLoad(): void;
33
39
  disconnectedCallback(): void;
34
40
  private cleanup;
41
+ private getErrorText;
35
42
  private startRecording;
36
43
  private setupMediaRecorder;
37
44
  private stopRecording;