ttp-agent-sdk 2.40.0 → 2.43.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/dist/agent-widget.dev.js +1220 -891
- package/dist/agent-widget.dev.js.map +1 -1
- package/dist/agent-widget.esm.js +1 -1
- package/dist/agent-widget.esm.js.map +1 -1
- package/dist/agent-widget.js +1 -1
- package/dist/agent-widget.js.map +1 -1
- package/dist/audio-processor.js +4 -0
- package/dist/demos/test-ecommerce.html +1 -1
- package/dist/demos/test-tour.html +0 -1
- package/dist/demos/widget-customization-dev.html +8 -14
- package/dist/demos/widget-customization.html +42 -10
- package/dist/examples/test-ecommerce.html +1 -1
- package/dist/examples/test-restaurant.html +16 -15
- package/dist/examples/test-text-chat.html +18 -9
- package/dist/examples/test-tour.html +0 -1
- package/dist/examples/widget-customization-dev.html +8 -14
- package/dist/examples/widget-customization.html +42 -10
- package/examples/test-ecommerce.html +1 -1
- package/examples/test-restaurant.html +16 -15
- package/examples/test-text-chat.html +18 -9
- package/examples/test-tour.html +0 -1
- package/examples/widget-customization-dev.html +8 -14
- package/examples/widget-customization.html +42 -10
- package/package.json +1 -1
package/dist/agent-widget.dev.js
CHANGED
|
@@ -9707,6 +9707,30 @@ function buildAudioConstraints(sampleRate) {
|
|
|
9707
9707
|
}
|
|
9708
9708
|
return _objectSpread(_objectSpread({}, base), userOverrides);
|
|
9709
9709
|
}
|
|
9710
|
+
|
|
9711
|
+
/**
|
|
9712
|
+
* Linear PCM16 resample (main thread). Safari/iOS often runs AudioContext at 44.1/48 kHz
|
|
9713
|
+
* while the voice server expects hello_ack inputSampleRate (e.g. 16 kHz).
|
|
9714
|
+
*/
|
|
9715
|
+
function resamplePCM16Linear(input, fromRate, toRate) {
|
|
9716
|
+
if (!input || input.length === 0 || fromRate === toRate) {
|
|
9717
|
+
return input;
|
|
9718
|
+
}
|
|
9719
|
+
var ratio = fromRate / toRate;
|
|
9720
|
+
var outLength = Math.max(1, Math.floor(input.length / ratio));
|
|
9721
|
+
var output = new Int16Array(outLength);
|
|
9722
|
+
for (var i = 0; i < outLength; i++) {
|
|
9723
|
+
var srcPos = i * ratio;
|
|
9724
|
+
var i0 = Math.floor(srcPos);
|
|
9725
|
+
var i1 = Math.min(i0 + 1, input.length - 1);
|
|
9726
|
+
var frac = srcPos - i0;
|
|
9727
|
+
var s0 = input[i0];
|
|
9728
|
+
var s1 = input[i1];
|
|
9729
|
+
var s = s0 + (s1 - s0) * frac;
|
|
9730
|
+
output[i] = Math.max(-32768, Math.min(32767, Math.round(s)));
|
|
9731
|
+
}
|
|
9732
|
+
return output;
|
|
9733
|
+
}
|
|
9710
9734
|
var _sharedRecorderContext = null;
|
|
9711
9735
|
var _sharedRecorderSampleRate = null;
|
|
9712
9736
|
var _sharedRecorderWorkletLoaded = false;
|
|
@@ -9719,6 +9743,7 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
|
|
|
9719
9743
|
_this.config = config;
|
|
9720
9744
|
_this.audioContext = null;
|
|
9721
9745
|
_this.audioWorkletNode = null;
|
|
9746
|
+
_this._recorderSinkGain = null;
|
|
9722
9747
|
_this.mediaStream = null;
|
|
9723
9748
|
_this.isRecording = false;
|
|
9724
9749
|
_this._starting = false;
|
|
@@ -9923,6 +9948,8 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
|
|
|
9923
9948
|
_isConnected2,
|
|
9924
9949
|
_error2,
|
|
9925
9950
|
source,
|
|
9951
|
+
negotiatedRate,
|
|
9952
|
+
contextRate,
|
|
9926
9953
|
userMessage,
|
|
9927
9954
|
_permissionState,
|
|
9928
9955
|
enhancedError,
|
|
@@ -10129,16 +10156,34 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
|
|
|
10129
10156
|
source = this.audioContext.createMediaStreamSource(this.mediaStream);
|
|
10130
10157
|
source.connect(this.audioWorkletNode);
|
|
10131
10158
|
|
|
10159
|
+
// WebKit/iOS: a graph that dead-ends at an AudioWorkletNode may not be pulled; force a
|
|
10160
|
+
// silent sink so the worklet process() runs reliably (no audible output).
|
|
10161
|
+
this._recorderSinkGain = this.audioContext.createGain();
|
|
10162
|
+
this._recorderSinkGain.gain.value = 0;
|
|
10163
|
+
this.audioWorkletNode.connect(this._recorderSinkGain);
|
|
10164
|
+
this._recorderSinkGain.connect(this.audioContext.destination);
|
|
10165
|
+
|
|
10132
10166
|
// Store source reference so we can disconnect it when stopping
|
|
10133
10167
|
this.mediaStreamSource = source;
|
|
10168
|
+
negotiatedRate = this.config.sampleRate || 16000;
|
|
10169
|
+
contextRate = this.audioContext.sampleRate;
|
|
10170
|
+
if (Math.abs(contextRate - negotiatedRate) > 1) {
|
|
10171
|
+
console.log("\u2139\uFE0F AudioRecorder: Context sample rate ".concat(contextRate, "Hz \u2260 negotiated uplink ").concat(negotiatedRate, "Hz \u2014 resampling in main thread"));
|
|
10172
|
+
}
|
|
10134
10173
|
|
|
10135
10174
|
// Handle messages from AudioWorklet
|
|
10136
10175
|
this.audioWorkletNode.port.onmessage = function (event) {
|
|
10137
|
-
var
|
|
10138
|
-
|
|
10139
|
-
data =
|
|
10176
|
+
var payload = event.data;
|
|
10177
|
+
var type = payload.type,
|
|
10178
|
+
data = payload.data;
|
|
10140
10179
|
if (type === 'pcm_audio_data') {
|
|
10141
|
-
|
|
10180
|
+
var chunkRate = payload.sampleRate || contextRate;
|
|
10181
|
+
var targetRate = _this2.config.sampleRate || 16000;
|
|
10182
|
+
if (chunkRate && targetRate && Math.abs(chunkRate - targetRate) > 1) {
|
|
10183
|
+
_this2.emit('audioData', resamplePCM16Linear(data, chunkRate, targetRate));
|
|
10184
|
+
} else {
|
|
10185
|
+
_this2.emit('audioData', data);
|
|
10186
|
+
}
|
|
10142
10187
|
}
|
|
10143
10188
|
};
|
|
10144
10189
|
|
|
@@ -10285,6 +10330,15 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
|
|
|
10285
10330
|
console.log('⚠️ AudioRecorder: AudioWorkletNode already disconnected');
|
|
10286
10331
|
}
|
|
10287
10332
|
case 4:
|
|
10333
|
+
if (this._recorderSinkGain) {
|
|
10334
|
+
try {
|
|
10335
|
+
this._recorderSinkGain.disconnect();
|
|
10336
|
+
} catch (e) {
|
|
10337
|
+
/* ignore */
|
|
10338
|
+
}
|
|
10339
|
+
this._recorderSinkGain = null;
|
|
10340
|
+
}
|
|
10341
|
+
|
|
10288
10342
|
// Stop media stream tracks (this stops microphone access)
|
|
10289
10343
|
if (this.mediaStream) {
|
|
10290
10344
|
console.log('🛑 AudioRecorder: Stopping media stream tracks...');
|
|
@@ -10432,6 +10486,78 @@ var AudioRecorder = /*#__PURE__*/function (_EventEmitter) {
|
|
|
10432
10486
|
_sharedRecorderWorkletLoaded = false;
|
|
10433
10487
|
_sharedRecorderWorkletPath = null;
|
|
10434
10488
|
}
|
|
10489
|
+
|
|
10490
|
+
/**
|
|
10491
|
+
* Create or resume the shared recorder AudioContext during the user-gesture window (e.g. right
|
|
10492
|
+
* after getUserMedia on mobile). Reduces iOS failures when recording starts only after a long
|
|
10493
|
+
* async WebSocket / hello_ack wait.
|
|
10494
|
+
*/
|
|
10495
|
+
}, {
|
|
10496
|
+
key: "primeSharedContext",
|
|
10497
|
+
value: (function () {
|
|
10498
|
+
var _primeSharedContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
10499
|
+
var sampleRateHint,
|
|
10500
|
+
rate,
|
|
10501
|
+
ctx,
|
|
10502
|
+
_args7 = arguments,
|
|
10503
|
+
_t7;
|
|
10504
|
+
return _regenerator().w(function (_context7) {
|
|
10505
|
+
while (1) switch (_context7.p = _context7.n) {
|
|
10506
|
+
case 0:
|
|
10507
|
+
sampleRateHint = _args7.length > 0 && _args7[0] !== undefined ? _args7[0] : 16000;
|
|
10508
|
+
if (!(typeof window === 'undefined')) {
|
|
10509
|
+
_context7.n = 1;
|
|
10510
|
+
break;
|
|
10511
|
+
}
|
|
10512
|
+
return _context7.a(2);
|
|
10513
|
+
case 1:
|
|
10514
|
+
rate = sampleRateHint || 16000;
|
|
10515
|
+
_context7.p = 2;
|
|
10516
|
+
if (!(_sharedRecorderContext && _sharedRecorderContext.state !== 'closed')) {
|
|
10517
|
+
_context7.n = 4;
|
|
10518
|
+
break;
|
|
10519
|
+
}
|
|
10520
|
+
if (!(_sharedRecorderContext.state === 'suspended')) {
|
|
10521
|
+
_context7.n = 3;
|
|
10522
|
+
break;
|
|
10523
|
+
}
|
|
10524
|
+
_context7.n = 3;
|
|
10525
|
+
return _sharedRecorderContext.resume();
|
|
10526
|
+
case 3:
|
|
10527
|
+
console.log('♻️ AudioRecorder.primeSharedContext: reused context', _sharedRecorderContext.sampleRate, 'Hz');
|
|
10528
|
+
return _context7.a(2);
|
|
10529
|
+
case 4:
|
|
10530
|
+
ctx = new (window.AudioContext || window.webkitAudioContext)({
|
|
10531
|
+
sampleRate: rate
|
|
10532
|
+
});
|
|
10533
|
+
_sharedRecorderContext = ctx;
|
|
10534
|
+
_sharedRecorderSampleRate = rate;
|
|
10535
|
+
_sharedRecorderWorkletLoaded = false;
|
|
10536
|
+
_sharedRecorderWorkletPath = null;
|
|
10537
|
+
if (!(ctx.state === 'suspended')) {
|
|
10538
|
+
_context7.n = 5;
|
|
10539
|
+
break;
|
|
10540
|
+
}
|
|
10541
|
+
_context7.n = 5;
|
|
10542
|
+
return ctx.resume();
|
|
10543
|
+
case 5:
|
|
10544
|
+
console.log('🎵 AudioRecorder.primeSharedContext: primed requested', rate, 'Hz, actual', ctx.sampleRate, 'Hz');
|
|
10545
|
+
_context7.n = 7;
|
|
10546
|
+
break;
|
|
10547
|
+
case 6:
|
|
10548
|
+
_context7.p = 6;
|
|
10549
|
+
_t7 = _context7.v;
|
|
10550
|
+
console.warn('⚠️ AudioRecorder.primeSharedContext failed (non-fatal):', _t7);
|
|
10551
|
+
case 7:
|
|
10552
|
+
return _context7.a(2);
|
|
10553
|
+
}
|
|
10554
|
+
}, _callee7, null, [[2, 6]]);
|
|
10555
|
+
}));
|
|
10556
|
+
function primeSharedContext() {
|
|
10557
|
+
return _primeSharedContext.apply(this, arguments);
|
|
10558
|
+
}
|
|
10559
|
+
return primeSharedContext;
|
|
10560
|
+
}())
|
|
10435
10561
|
}]);
|
|
10436
10562
|
}(_EventEmitter_js__WEBPACK_IMPORTED_MODULE_0__["default"]);
|
|
10437
10563
|
|
|
@@ -15645,8 +15771,22 @@ var FLAVORS = {
|
|
|
15645
15771
|
restaurants: _restaurants_js__WEBPACK_IMPORTED_MODULE_2__.createRestaurantsFlavor,
|
|
15646
15772
|
tours: _tours_js__WEBPACK_IMPORTED_MODULE_3__.createToursFlavor
|
|
15647
15773
|
};
|
|
15774
|
+
|
|
15775
|
+
/** Common client typos / aliases → canonical keys in FLAVORS */
|
|
15776
|
+
var FLAVOR_ALIASES = {
|
|
15777
|
+
resturants: 'restaurants'
|
|
15778
|
+
};
|
|
15779
|
+
|
|
15780
|
+
/**
|
|
15781
|
+
* Resolve a widget flavor name to a registered factory.
|
|
15782
|
+
* Accepts case-insensitive keys and known aliases (e.g. resturants → restaurants).
|
|
15783
|
+
*/
|
|
15648
15784
|
function loadFlavor(name) {
|
|
15649
|
-
|
|
15785
|
+
if (name == null || typeof name !== 'string') {
|
|
15786
|
+
return null;
|
|
15787
|
+
}
|
|
15788
|
+
var key = FLAVOR_ALIASES[name.trim().toLowerCase()] || name.trim().toLowerCase();
|
|
15789
|
+
return FLAVORS[key] || null;
|
|
15650
15790
|
}
|
|
15651
15791
|
|
|
15652
15792
|
/***/ }),
|
|
@@ -17324,8 +17464,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
17324
17464
|
|
|
17325
17465
|
|
|
17326
17466
|
// Version - injected at build time from package.json via webpack DefinePlugin
|
|
17327
|
-
var VERSION = "2.
|
|
17328
|
-
var BUILD_TIME = "2026-03-
|
|
17467
|
+
var VERSION = "2.43.0";
|
|
17468
|
+
var BUILD_TIME = "2026-03-26T01:57:03.238Z";
|
|
17329
17469
|
console.log("%c TTP Agent SDK v".concat(VERSION, " (").concat(BUILD_TIME, ") "), 'background: #4f46e5; color: white; font-size: 12px; font-weight: bold; padding: 2px 6px; border-radius: 4px;');
|
|
17330
17470
|
|
|
17331
17471
|
// Named exports
|
|
@@ -18376,7 +18516,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
18376
18516
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
18377
18517
|
/* harmony export */ showBlockedModal: () => (/* binding */ showBlockedModal),
|
|
18378
18518
|
/* harmony export */ showNoMicrophoneModal: () => (/* binding */ showNoMicrophoneModal),
|
|
18379
|
-
/* harmony export */ showPrePromptModal: () => (/* binding */ showPrePromptModal)
|
|
18519
|
+
/* harmony export */ showPrePromptModal: () => (/* binding */ showPrePromptModal),
|
|
18520
|
+
/* harmony export */ showServerDisclaimerModal: () => (/* binding */ showServerDisclaimerModal)
|
|
18380
18521
|
/* harmony export */ });
|
|
18381
18522
|
/* harmony import */ var _MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MicPermissionUtils.js */ "./src/shared/MicPermissionUtils.js");
|
|
18382
18523
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
@@ -18538,6 +18679,7 @@ var MicPermissionModal = /*#__PURE__*/function () {
|
|
|
18538
18679
|
value: function createOverlay() {
|
|
18539
18680
|
var overlay = document.createElement('div');
|
|
18540
18681
|
overlay.className = 'mic-permission-overlay';
|
|
18682
|
+
overlay.setAttribute('dir', 'ltr');
|
|
18541
18683
|
overlay.style.cssText = "\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n ";
|
|
18542
18684
|
|
|
18543
18685
|
// Add fade-in animation if not already added
|
|
@@ -18558,7 +18700,7 @@ var MicPermissionModal = /*#__PURE__*/function () {
|
|
|
18558
18700
|
}
|
|
18559
18701
|
var style = document.createElement('style');
|
|
18560
18702
|
style.id = 'mic-permission-styles';
|
|
18561
|
-
style.textContent = "\n @keyframes mic-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes mic-slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n @keyframes mic-bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-5px); }\n }\n \n .mic-permission-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n }\n \n .mic-permission-modal {\n background: #ffffff;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 480px;\n width: 100%;\n padding: 32px;\n position: relative;\n animation: mic-slideUp 0.3s ease-out;\n max-height: 90vh;\n overflow-y: auto;\n }\n \n .mic-permission-modal__close {\n position: absolute;\n top: 16px;\n right: 16px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #6b7280;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n \n .mic-permission-modal__close:hover {\n background: #e5e7eb;\n }\n \n .mic-permission-modal__icon {\n font-size: 48px;\n text-align: center;\n margin-bottom: 16px;\n }\n \n .mic-permission-modal__title {\n font-size: 24px;\n font-weight: 700;\n color: #111827;\n margin: 0 0 12px;\n line-height: 1.3;\n text-align: center;\n }\n \n .mic-permission-modal__description {\n color: #6b7280;\n font-size: 16px;\n line-height: 1.6;\n margin: 0 0 20px;\n text-align: center;\n }\n \n .mic-permission-modal__highlight {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #dbeafe, #ede9fe);\n padding: 16px 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 1px solid #bfdbfe;\n }\n \n .mic-permission-modal__highlight-icon {\n font-size: 24px;\n animation: mic-bounce 1s infinite;\n }\n \n .mic-permission-modal__status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: #fef2f2;\n color: #ef4444;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-weight: 500;\n }\n \n .mic-permission-modal__note {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n background: #fffbeb;\n color: #92400e;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid #fde68a;\n }\n \n .mic-permission-modal__steps {\n margin-bottom: 20px;\n }\n \n .mic-permission-modal__steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0 0 12px;\n }\n \n .mic-permission-modal__steps ol {\n margin: 0;\n padding-left: 24px;\n counter-reset: step-counter;\n list-style: none;\n }\n \n .mic-permission-modal__steps li {\n position: relative;\n padding: 12px 0 12px 16px;\n border-left: 2px solid #e5e7eb;\n color: #111827;\n font-size: 15px;\n line-height: 1.5;\n counter-increment: step-counter;\n }\n \n .mic-permission-modal__steps li::before {\n content: counter(step-counter);\n position: absolute;\n left: -14px;\n top: 10px;\n width: 24px;\n height: 24px;\n background: #4f46e5;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .mic-permission-modal__steps li:last-child {\n border-left-color: transparent;\n }\n \n .mic-permission-modal__actions {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 24px;\n }\n \n .mic-permission-modal__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 14px 24px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n border: none;\n width: 100%;\n }\n \n .mic-permission-modal__btn--primary {\n background: #4f46e5;\n color: white;\n }\n \n .mic-permission-modal__btn--primary:hover {\n background: #4338ca;\n transform: translateY(-1px);\n }\n \n .mic-permission-modal__btn--secondary {\n background: #e5e7eb;\n color: #111827;\n }\n \n .mic-permission-modal__btn--secondary:hover {\n background: #d1d5db;\n }\n \n .mic-permission-modal__footer {\n text-align: center;\n font-size: 13px;\n color: #6b7280;\n margin-top: 20px;\n margin-bottom: 0;\n }\n \n .mic-permission-modal__visual-guide {\n width: 100%;\n max-width: 380px;\n height: auto;\n margin: 20px auto;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: block;\n }\n \n .mic-permission-modal__visual-guide-container {\n text-align: center;\n margin: 20px 0;\n }\n \n @media (max-width: 480px) {\n .mic-permission-modal {\n padding: 24px 20px;\n margin: 10px;\n max-height: 85vh;\n }\n \n .mic-permission-modal__title {\n font-size: 20px;\n }\n \n .mic-permission-modal__icon {\n font-size: 40px;\n }\n \n .mic-permission-modal__visual-guide {\n max-width: 100%;\n }\n }\n \n /* Mobile pre-prompt: compact, action-first layout - buttons always visible above safe area */\n .mic-permission-modal--mobile {\n max-height: none;\n padding: 20px 20px 24px;\n padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));\n margin: 12px;\n align-self: flex-end;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__icon {\n font-size: 36px;\n margin-bottom: 12px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__title {\n font-size: 18px;\n margin-bottom: 8px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__description {\n font-size: 14px;\n margin-bottom: 12px;\n line-height: 1.5;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__highlight {\n padding: 12px 16px;\n margin-bottom: 12px;\n font-size: 14px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__note {\n padding: 10px 14px;\n margin-bottom: 16px;\n font-size: 13px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__actions {\n margin-top: 16px;\n gap: 10px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__btn {\n padding: 16px 24px;\n font-size: 16px;\n min-height: 48px;\n }\n ";
|
|
18703
|
+
style.textContent = "\n @keyframes mic-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n \n @keyframes mic-slideUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n \n @keyframes mic-bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-5px); }\n }\n \n /* direction ltr: host page may be RTL (e.g. Hebrew); keep overlay + modal English copy readable */\n .mic-permission-overlay {\n position: fixed;\n inset: 0;\n direction: ltr;\n background: rgba(0, 0, 0, 0.6);\n backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100001;\n padding: 20px;\n animation: mic-fadeIn 0.2s ease-out;\n }\n \n .mic-permission-modal {\n direction: ltr;\n unicode-bidi: isolate;\n background: #ffffff;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 480px;\n width: 100%;\n padding: 32px;\n position: relative;\n animation: mic-slideUp 0.3s ease-out;\n max-height: 90vh;\n overflow-y: auto;\n }\n \n .mic-permission-modal__close {\n position: absolute;\n top: 16px;\n right: 16px;\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n color: #6b7280;\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n \n .mic-permission-modal__close:hover {\n background: #e5e7eb;\n }\n \n .mic-permission-modal__icon {\n font-size: 48px;\n text-align: center;\n margin-bottom: 16px;\n }\n \n .mic-permission-modal__title {\n font-size: 24px;\n font-weight: 700;\n color: #111827;\n margin: 0 0 12px;\n line-height: 1.3;\n text-align: center;\n }\n \n .mic-permission-modal__description {\n color: #6b7280;\n font-size: 16px;\n line-height: 1.6;\n margin: 0 0 20px;\n text-align: center;\n }\n \n .mic-permission-modal__highlight {\n display: flex;\n align-items: center;\n gap: 12px;\n background: linear-gradient(135deg, #dbeafe, #ede9fe);\n padding: 16px 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n border: 1px solid #bfdbfe;\n }\n \n .mic-permission-modal__highlight-icon {\n font-size: 24px;\n animation: mic-bounce 1s infinite;\n }\n \n .mic-permission-modal__status {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n background: #fef2f2;\n color: #ef4444;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-weight: 500;\n }\n \n .mic-permission-modal__note {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n background: #fffbeb;\n color: #92400e;\n padding: 12px 16px;\n border-radius: 8px;\n margin-bottom: 20px;\n font-size: 14px;\n line-height: 1.5;\n border: 1px solid #fde68a;\n }\n \n .mic-permission-modal__steps {\n margin-bottom: 20px;\n }\n \n .mic-permission-modal__steps h3 {\n font-size: 14px;\n font-weight: 600;\n color: #6b7280;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0 0 12px;\n }\n \n .mic-permission-modal__steps ol {\n margin: 0;\n padding-left: 24px;\n counter-reset: step-counter;\n list-style: none;\n }\n \n .mic-permission-modal__steps li {\n position: relative;\n padding: 12px 0 12px 16px;\n border-left: 2px solid #e5e7eb;\n color: #111827;\n font-size: 15px;\n line-height: 1.5;\n counter-increment: step-counter;\n }\n \n .mic-permission-modal__steps li::before {\n content: counter(step-counter);\n position: absolute;\n left: -14px;\n top: 10px;\n width: 24px;\n height: 24px;\n background: #4f46e5;\n color: white;\n border-radius: 50%;\n font-size: 12px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .mic-permission-modal__steps li:last-child {\n border-left-color: transparent;\n }\n \n .mic-permission-modal__actions {\n display: flex;\n flex-direction: column;\n gap: 10px;\n margin-top: 24px;\n }\n \n .mic-permission-modal__btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 14px 24px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s;\n border: none;\n width: 100%;\n }\n \n .mic-permission-modal__btn--primary {\n background: #4f46e5;\n color: white;\n }\n \n .mic-permission-modal__btn--primary:hover {\n background: #4338ca;\n transform: translateY(-1px);\n }\n \n .mic-permission-modal__btn--secondary {\n background: #e5e7eb;\n color: #111827;\n }\n \n .mic-permission-modal__btn--secondary:hover {\n background: #d1d5db;\n }\n \n .mic-permission-modal__footer {\n text-align: center;\n font-size: 13px;\n color: #6b7280;\n margin-top: 20px;\n margin-bottom: 0;\n }\n \n .mic-permission-modal__visual-guide {\n width: 100%;\n max-width: 380px;\n height: auto;\n margin: 20px auto;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: block;\n }\n \n .mic-permission-modal__visual-guide-container {\n text-align: center;\n margin: 20px 0;\n }\n \n @media (max-width: 480px) {\n .mic-permission-modal {\n padding: 24px 20px;\n margin: 10px;\n max-height: 85vh;\n }\n \n .mic-permission-modal__title {\n font-size: 20px;\n }\n \n .mic-permission-modal__icon {\n font-size: 40px;\n }\n \n .mic-permission-modal__visual-guide {\n max-width: 100%;\n }\n }\n \n /* Mobile pre-prompt: compact, action-first layout - buttons always visible above safe area */\n .mic-permission-modal--mobile {\n max-height: none;\n padding: 20px 20px 24px;\n padding-bottom: max(24px, env(safe-area-inset-bottom, 24px));\n margin: 12px;\n align-self: flex-end;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__icon {\n font-size: 36px;\n margin-bottom: 12px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__title {\n font-size: 18px;\n margin-bottom: 8px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__description {\n font-size: 14px;\n margin-bottom: 12px;\n line-height: 1.5;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__highlight {\n padding: 12px 16px;\n margin-bottom: 12px;\n font-size: 14px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__note {\n padding: 10px 14px;\n margin-bottom: 16px;\n font-size: 13px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__actions {\n margin-top: 16px;\n gap: 10px;\n }\n \n .mic-permission-modal--mobile .mic-permission-modal__btn {\n padding: 16px 24px;\n font-size: 16px;\n min-height: 48px;\n }\n ";
|
|
18562
18704
|
document.head.appendChild(style);
|
|
18563
18705
|
}
|
|
18564
18706
|
|
|
@@ -18914,6 +19056,52 @@ function showNoMicrophoneModal(onClose) {
|
|
|
18914
19056
|
return modal;
|
|
18915
19057
|
}
|
|
18916
19058
|
|
|
19059
|
+
/**
|
|
19060
|
+
* Server-driven disclaimer (legal copy from backend hello_ack). Plain text only.
|
|
19061
|
+
*/
|
|
19062
|
+
function showServerDisclaimerModal(_ref) {
|
|
19063
|
+
var texts = _ref.texts,
|
|
19064
|
+
onAccept = _ref.onAccept,
|
|
19065
|
+
onCancel = _ref.onCancel;
|
|
19066
|
+
var modal = new MicPermissionModal();
|
|
19067
|
+
var overlay = modal.createOverlay();
|
|
19068
|
+
overlay.style.background = 'rgba(0, 0, 0, 0.5)';
|
|
19069
|
+
overlay.style.backdropFilter = 'blur(2px)';
|
|
19070
|
+
var isMobile = isMobileDevice();
|
|
19071
|
+
var modalDiv = document.createElement('div');
|
|
19072
|
+
modalDiv.className = 'mic-permission-modal' + (isMobile ? ' mic-permission-modal--mobile' : '');
|
|
19073
|
+
var lines = (texts || []).map(function (t) {
|
|
19074
|
+
return String(t).trim();
|
|
19075
|
+
}).filter(Boolean);
|
|
19076
|
+
var body = lines.length ? lines.join('\n\n') : 'Please confirm to continue.';
|
|
19077
|
+
var safe = body.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
19078
|
+
modalDiv.innerHTML = "\n <h2 class=\"mic-permission-modal__title\">Notice</h2>\n <div class=\"mic-permission-modal__description\" style=\"white-space:pre-wrap;max-height:50vh;overflow:auto;text-align:left;font-size:15px;line-height:1.5;\">".concat(safe, "</div>\n <div class=\"mic-permission-modal__actions\">\n <button type=\"button\" class=\"mic-permission-modal__btn mic-permission-modal__btn--primary\" data-action=\"accept\">Accept</button>\n <button type=\"button\" class=\"mic-permission-modal__btn mic-permission-modal__btn--secondary\" data-action=\"cancel\">Decline</button>\n </div>\n ");
|
|
19079
|
+
if (isMobile) {
|
|
19080
|
+
overlay.style.alignItems = 'flex-end';
|
|
19081
|
+
overlay.style.paddingBottom = 'max(20px, env(safe-area-inset-bottom, 20px))';
|
|
19082
|
+
overlay.style.paddingTop = '20px';
|
|
19083
|
+
}
|
|
19084
|
+
overlay.appendChild(modalDiv);
|
|
19085
|
+
modal.overlay = overlay;
|
|
19086
|
+
modal.modal = modalDiv;
|
|
19087
|
+
modalDiv.querySelector('[data-action="accept"]').addEventListener('click', function () {
|
|
19088
|
+
modal.close();
|
|
19089
|
+
onAccept();
|
|
19090
|
+
});
|
|
19091
|
+
modalDiv.querySelector('[data-action="cancel"]').addEventListener('click', function () {
|
|
19092
|
+
modal.close();
|
|
19093
|
+
onCancel();
|
|
19094
|
+
});
|
|
19095
|
+
overlay.addEventListener('click', function (e) {
|
|
19096
|
+
if (e.target === overlay) {
|
|
19097
|
+
modal.close();
|
|
19098
|
+
onCancel();
|
|
19099
|
+
}
|
|
19100
|
+
});
|
|
19101
|
+
modal.show();
|
|
19102
|
+
return modal;
|
|
19103
|
+
}
|
|
19104
|
+
|
|
18917
19105
|
/***/ }),
|
|
18918
19106
|
|
|
18919
19107
|
/***/ "./src/shared/MicPermissionUtils.js":
|
|
@@ -18928,7 +19116,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
18928
19116
|
/* harmony export */ checkPermissionState: () => (/* binding */ checkPermissionState),
|
|
18929
19117
|
/* harmony export */ getDeviceInfo: () => (/* binding */ getDeviceInfo),
|
|
18930
19118
|
/* harmony export */ getPermissionInstructions: () => (/* binding */ getPermissionInstructions),
|
|
18931
|
-
/* harmony export */ openSettings: () => (/* binding */ openSettings)
|
|
19119
|
+
/* harmony export */ openSettings: () => (/* binding */ openSettings),
|
|
19120
|
+
/* harmony export */ shouldUseMobileVoiceCallUI: () => (/* binding */ shouldUseMobileVoiceCallUI)
|
|
18932
19121
|
/* harmony export */ });
|
|
18933
19122
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
18934
19123
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
@@ -18996,6 +19185,28 @@ function getDeviceInfo() {
|
|
|
18996
19185
|
};
|
|
18997
19186
|
}
|
|
18998
19187
|
|
|
19188
|
+
/**
|
|
19189
|
+
* Use the compact mobile voice-call UI (minimized bar + transcript overlay).
|
|
19190
|
+
* Native iOS/Android always use it. Other cases: viewport ≤768px and touch/coarse pointer
|
|
19191
|
+
* (in-app browsers, Instagram/Facebook WebViews with desktop UA, etc.).
|
|
19192
|
+
*/
|
|
19193
|
+
function shouldUseMobileVoiceCallUI() {
|
|
19194
|
+
var _getDeviceInfo = getDeviceInfo(),
|
|
19195
|
+
isIOS = _getDeviceInfo.isIOS,
|
|
19196
|
+
isAndroid = _getDeviceInfo.isAndroid;
|
|
19197
|
+
if (isIOS || isAndroid) return true;
|
|
19198
|
+
if (typeof window === 'undefined') return false;
|
|
19199
|
+
if (window.innerWidth > 768) return false;
|
|
19200
|
+
var touchCapable = navigator.maxTouchPoints > 0;
|
|
19201
|
+
var coarsePointer = false;
|
|
19202
|
+
try {
|
|
19203
|
+
coarsePointer = window.matchMedia('(pointer: coarse)').matches;
|
|
19204
|
+
} catch (_) {
|
|
19205
|
+
/* matchMedia unsupported */
|
|
19206
|
+
}
|
|
19207
|
+
return touchCapable || coarsePointer;
|
|
19208
|
+
}
|
|
19209
|
+
|
|
18999
19210
|
/**
|
|
19000
19211
|
* Check microphone permission state using Permissions API
|
|
19001
19212
|
* Returns 'granted', 'denied', 'prompt', or 'unknown'
|
|
@@ -23541,6 +23752,9 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
23541
23752
|
* - 'dataInjected' - Data injection successfully acknowledged by server
|
|
23542
23753
|
*
|
|
23543
23754
|
* - 'dataInjectionError' - Data injection failed (validation, timeout, or server error)
|
|
23755
|
+
*
|
|
23756
|
+
* - 'disclaimersRequired' - Server requires disclaimer acknowledgement (payload: texts, disclaimersHash, ...)
|
|
23757
|
+
* - 'disclaimerRejected' - Server closed or rejected disclaimer ({ code, message })
|
|
23544
23758
|
|
|
23545
23759
|
*/
|
|
23546
23760
|
var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
@@ -23609,6 +23823,18 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
23609
23823
|
_this.hasEverConnected = false; // Track if we've successfully connected at least once
|
|
23610
23824
|
|
|
23611
23825
|
_this.helloAckReceived = false;
|
|
23826
|
+
|
|
23827
|
+
/** When true, server hello_ack requires disclaimer_ack before STT/greeting; block recording until cleared */
|
|
23828
|
+
_this.disclaimersPending = false;
|
|
23829
|
+
|
|
23830
|
+
/** Server copy hash (SHA-256) echoed in disclaimer_ack */
|
|
23831
|
+
_this.disclaimersHash = null;
|
|
23832
|
+
|
|
23833
|
+
/** Last server disclaimer payload (for UI) */
|
|
23834
|
+
_this.lastDisclaimerPayload = null;
|
|
23835
|
+
|
|
23836
|
+
/** Set when hangup() runs with an open socket — skip resume-key clear in destroy() */
|
|
23837
|
+
_this._gracefulHangupInitiated = false;
|
|
23612
23838
|
_this.isRecording = false;
|
|
23613
23839
|
_this.isPlaying = false;
|
|
23614
23840
|
_this.isDestroyed = false;
|
|
@@ -24379,6 +24605,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24379
24605
|
console.log('🔌 VoiceSDK v2: WebSocket closed:', event.code, event.reason);
|
|
24380
24606
|
_this6.isConnected = false;
|
|
24381
24607
|
_this6.helloAckReceived = false;
|
|
24608
|
+
_this6.disclaimersPending = false;
|
|
24382
24609
|
|
|
24383
24610
|
// Stop recording if active
|
|
24384
24611
|
|
|
@@ -24566,7 +24793,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24566
24793
|
|
|
24567
24794
|
// Include SDK build time for debugging
|
|
24568
24795
|
if (true) {
|
|
24569
|
-
helloMessage.lastBuildTime = "2026-03-
|
|
24796
|
+
helloMessage.lastBuildTime = "2026-03-26T01:57:03.238Z";
|
|
24570
24797
|
}
|
|
24571
24798
|
|
|
24572
24799
|
// TEMPORARILY DISABLED: Always attach page context - backend decides what to use
|
|
@@ -24698,6 +24925,19 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24698
24925
|
this.emit('message', message);
|
|
24699
24926
|
break;
|
|
24700
24927
|
case 'error':
|
|
24928
|
+
if (message.code && String(message.code).startsWith('DISCLAIMER_')) {
|
|
24929
|
+
if (message.code === 'DISCLAIMER_PENDING') {
|
|
24930
|
+
var err = new Error(message.message || 'Disclaimer acknowledgement required first');
|
|
24931
|
+
err.code = 'DISCLAIMER_PENDING';
|
|
24932
|
+
this.emit('error', err);
|
|
24933
|
+
} else {
|
|
24934
|
+
this.disclaimersPending = false;
|
|
24935
|
+
this.emit('disclaimerRejected', {
|
|
24936
|
+
code: message.code,
|
|
24937
|
+
message: message.message || ''
|
|
24938
|
+
});
|
|
24939
|
+
}
|
|
24940
|
+
}
|
|
24701
24941
|
this.emit('message', message);
|
|
24702
24942
|
break;
|
|
24703
24943
|
case 'barge_in':
|
|
@@ -24832,10 +25072,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24832
25072
|
console.warn('⚠️ [VISUAL ASSISTANT] Screenshot error:', message.error);
|
|
24833
25073
|
}
|
|
24834
25074
|
break;
|
|
25075
|
+
case 'show_items':
|
|
24835
25076
|
case 'show_products':
|
|
24836
25077
|
case 'cart_updated':
|
|
24837
25078
|
case 'add_to_store_cart':
|
|
24838
|
-
//
|
|
25079
|
+
// Flavor / commerce messages (show_items = menu, rooms, tours, etc.)
|
|
24839
25080
|
this.emit('message', message);
|
|
24840
25081
|
break;
|
|
24841
25082
|
default:
|
|
@@ -25073,6 +25314,10 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25073
25314
|
this.emit('inputFormatNegotiated', message.inputAudioFormat);
|
|
25074
25315
|
}
|
|
25075
25316
|
|
|
25317
|
+
// Server-driven disclaimer gate (voice): when true, client must send disclaimer_ack before using the session.
|
|
25318
|
+
this.disclaimersPending = message.disclaimersRequired === true;
|
|
25319
|
+
this.disclaimersHash = this.disclaimersPending ? message.disclaimersHash || null : null;
|
|
25320
|
+
|
|
25076
25321
|
// IMPORTANT: Set this AFTER input format negotiation above.
|
|
25077
25322
|
// VoiceInterface waits for this flag before starting recording,
|
|
25078
25323
|
// so config.sampleRate must be finalized first.
|
|
@@ -25170,6 +25415,47 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25170
25415
|
this.audioPlayer.setOutputFormat(defaultFormat);
|
|
25171
25416
|
this.formatConverter = null; // No conversion needed when using defaults
|
|
25172
25417
|
}
|
|
25418
|
+
if (this.disclaimersPending) {
|
|
25419
|
+
var payload = {
|
|
25420
|
+
texts: Array.isArray(message.disclaimerTexts) ? message.disclaimerTexts : [],
|
|
25421
|
+
disclaimersHash: this.disclaimersHash,
|
|
25422
|
+
disclaimersVersion: message.disclaimersVersion,
|
|
25423
|
+
disclaimerTimeoutMs: message.disclaimerTimeoutMs,
|
|
25424
|
+
conversationId: this.conversationId
|
|
25425
|
+
};
|
|
25426
|
+
this.lastDisclaimerPayload = payload;
|
|
25427
|
+
this.emit('disclaimersRequired', payload);
|
|
25428
|
+
} else {
|
|
25429
|
+
this.lastDisclaimerPayload = null;
|
|
25430
|
+
}
|
|
25431
|
+
}
|
|
25432
|
+
|
|
25433
|
+
/**
|
|
25434
|
+
* Acknowledge server disclaimer gate (voice protocol).
|
|
25435
|
+
* @param {boolean} accepted
|
|
25436
|
+
*/
|
|
25437
|
+
}, {
|
|
25438
|
+
key: "sendDisclaimerAck",
|
|
25439
|
+
value: function sendDisclaimerAck(accepted) {
|
|
25440
|
+
if (!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
|
|
25441
|
+
console.warn('VoiceSDK v2: Cannot send disclaimer_ack — socket not open');
|
|
25442
|
+
return;
|
|
25443
|
+
}
|
|
25444
|
+
var payload = {
|
|
25445
|
+
t: 'disclaimer_ack',
|
|
25446
|
+
accepted: !!accepted,
|
|
25447
|
+
disclaimersHash: this.disclaimersHash || '',
|
|
25448
|
+
conversationId: this.conversationId || undefined
|
|
25449
|
+
};
|
|
25450
|
+
try {
|
|
25451
|
+
this.websocket.send(JSON.stringify(payload));
|
|
25452
|
+
console.log('📤 VoiceSDK v2: disclaimer_ack sent', {
|
|
25453
|
+
accepted: payload.accepted
|
|
25454
|
+
});
|
|
25455
|
+
this.disclaimersPending = false;
|
|
25456
|
+
} catch (e) {
|
|
25457
|
+
console.error('VoiceSDK v2: disclaimer_ack send failed', e);
|
|
25458
|
+
}
|
|
25173
25459
|
}
|
|
25174
25460
|
|
|
25175
25461
|
/**
|
|
@@ -25649,6 +25935,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25649
25935
|
return;
|
|
25650
25936
|
}
|
|
25651
25937
|
console.log('📞 VoiceSDK v2: Hanging up call...');
|
|
25938
|
+
this._gracefulHangupInitiated = true;
|
|
25652
25939
|
|
|
25653
25940
|
// Clear stored conversationId on graceful hangup
|
|
25654
25941
|
// This prevents attempting resume after intentional end
|
|
@@ -25702,6 +25989,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25702
25989
|
var existingMediaStream,
|
|
25703
25990
|
error,
|
|
25704
25991
|
_error4,
|
|
25992
|
+
_error5,
|
|
25705
25993
|
permissionError,
|
|
25706
25994
|
_args6 = arguments,
|
|
25707
25995
|
_t4,
|
|
@@ -25726,40 +26014,49 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25726
26014
|
console.warn('VoiceSDK v2: Already recording');
|
|
25727
26015
|
return _context6.a(2, true);
|
|
25728
26016
|
case 2:
|
|
26017
|
+
if (!this.disclaimersPending) {
|
|
26018
|
+
_context6.n = 3;
|
|
26019
|
+
break;
|
|
26020
|
+
}
|
|
26021
|
+
_error4 = new Error('Server disclaimers must be accepted before recording. Call sendDisclaimerAck(true) first.');
|
|
26022
|
+
_error4.code = 'DISCLAIMER_PENDING';
|
|
26023
|
+
this.emit('error', _error4);
|
|
26024
|
+
throw _error4;
|
|
26025
|
+
case 3:
|
|
25729
26026
|
console.log('🎤 VoiceSDK v2: Starting recording...');
|
|
25730
|
-
_context6.p =
|
|
26027
|
+
_context6.p = 4;
|
|
25731
26028
|
// CRITICAL for mobile browsers: Request microphone permission FIRST
|
|
25732
26029
|
// iOS: Pass existingMediaStream to avoid second getUserMedia (can fail on iOS)
|
|
25733
26030
|
console.log('🎤 VoiceSDK v2: Requesting microphone permission (mobile-friendly)...');
|
|
25734
|
-
_context6.n =
|
|
26031
|
+
_context6.n = 5;
|
|
25735
26032
|
return this.audioRecorder.start(existingMediaStream ? {
|
|
25736
26033
|
existingMediaStream: existingMediaStream
|
|
25737
26034
|
} : {});
|
|
25738
|
-
case
|
|
26035
|
+
case 5:
|
|
25739
26036
|
if (!(!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN)) {
|
|
25740
|
-
_context6.n =
|
|
26037
|
+
_context6.n = 10;
|
|
25741
26038
|
break;
|
|
25742
26039
|
}
|
|
25743
|
-
_context6.p =
|
|
25744
|
-
_context6.n =
|
|
26040
|
+
_context6.p = 6;
|
|
26041
|
+
_context6.n = 7;
|
|
25745
26042
|
return this.audioRecorder.stop();
|
|
25746
|
-
case 6:
|
|
25747
|
-
_context6.n = 8;
|
|
25748
|
-
break;
|
|
25749
26043
|
case 7:
|
|
25750
|
-
_context6.
|
|
25751
|
-
|
|
26044
|
+
_context6.n = 9;
|
|
26045
|
+
break;
|
|
25752
26046
|
case 8:
|
|
25753
|
-
|
|
25754
|
-
|
|
25755
|
-
|
|
26047
|
+
_context6.p = 8;
|
|
26048
|
+
_t4 = _context6.v;
|
|
26049
|
+
case 9:
|
|
26050
|
+
_error5 = new Error('Connection lost - server may have rejected the call');
|
|
26051
|
+
_error5.name = 'ServerRejected';
|
|
26052
|
+
_error5.isServerRejection = true;
|
|
25756
26053
|
// Don't emit error event - this is expected when server rejects
|
|
25757
26054
|
// The error handler in VoiceInterface will handle it appropriately
|
|
25758
|
-
throw
|
|
25759
|
-
case 9:
|
|
25760
|
-
_context6.n = 10;
|
|
25761
|
-
return this.audioPlayer.resumeAudioContext();
|
|
26055
|
+
throw _error5;
|
|
25762
26056
|
case 10:
|
|
26057
|
+
_context6.n = 11;
|
|
26058
|
+
return this.audioPlayer.resumeAudioContext();
|
|
26059
|
+
case 11:
|
|
25763
26060
|
// After permission is granted, send start_continuous_mode message to server
|
|
25764
26061
|
this.sendMessage({
|
|
25765
26062
|
t: 'start_continuous_mode',
|
|
@@ -25769,29 +26066,29 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25769
26066
|
// Request screen wake lock to keep screen on during voice call (mobile)
|
|
25770
26067
|
this._requestWakeLock();
|
|
25771
26068
|
return _context6.a(2, true);
|
|
25772
|
-
case
|
|
25773
|
-
_context6.p =
|
|
26069
|
+
case 12:
|
|
26070
|
+
_context6.p = 12;
|
|
25774
26071
|
_t5 = _context6.v;
|
|
25775
26072
|
if (!(this.audioRecorder && this.audioRecorder.isRecording)) {
|
|
25776
|
-
_context6.n =
|
|
26073
|
+
_context6.n = 16;
|
|
25777
26074
|
break;
|
|
25778
26075
|
}
|
|
25779
|
-
_context6.p =
|
|
25780
|
-
_context6.n =
|
|
26076
|
+
_context6.p = 13;
|
|
26077
|
+
_context6.n = 14;
|
|
25781
26078
|
return this.audioRecorder.stop();
|
|
25782
|
-
case 13:
|
|
25783
|
-
_context6.n = 15;
|
|
25784
|
-
break;
|
|
25785
26079
|
case 14:
|
|
25786
|
-
_context6.
|
|
25787
|
-
|
|
26080
|
+
_context6.n = 16;
|
|
26081
|
+
break;
|
|
25788
26082
|
case 15:
|
|
26083
|
+
_context6.p = 15;
|
|
26084
|
+
_t6 = _context6.v;
|
|
26085
|
+
case 16:
|
|
25789
26086
|
if (!(_t5.isServerRejection || _t5.name === 'ServerRejected')) {
|
|
25790
|
-
_context6.n =
|
|
26087
|
+
_context6.n = 17;
|
|
25791
26088
|
break;
|
|
25792
26089
|
}
|
|
25793
26090
|
return _context6.a(2, false);
|
|
25794
|
-
case
|
|
26091
|
+
case 17:
|
|
25795
26092
|
// Log and emit other errors (permission denied, etc.)
|
|
25796
26093
|
console.error('❌ VoiceSDK v2: Failed to start recording:', _t5);
|
|
25797
26094
|
|
|
@@ -25806,7 +26103,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
25806
26103
|
}
|
|
25807
26104
|
return _context6.a(2, false);
|
|
25808
26105
|
}
|
|
25809
|
-
}, _callee6, this, [[
|
|
26106
|
+
}, _callee6, this, [[13, 15], [6, 8], [4, 12]]);
|
|
25810
26107
|
}));
|
|
25811
26108
|
function startRecording() {
|
|
25812
26109
|
return _startRecording.apply(this, arguments);
|
|
@@ -26198,6 +26495,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26198
26495
|
}
|
|
26199
26496
|
this.isConnected = false;
|
|
26200
26497
|
|
|
26498
|
+
// hello_ack calls storeConversationId(), which refreshes RESUME_TTL_MS. If connect
|
|
26499
|
+
// then aborts (mic denied, disconnect, etc.) without hangup(), sessionStorage still
|
|
26500
|
+
// looks like a fresh in-call navigation and the widget auto-resumes on refresh.
|
|
26501
|
+
// Graceful hangup() clears storage and sets _gracefulHangupInitiated — do not wipe here.
|
|
26502
|
+
if (this.helloAckReceived && !this._gracefulHangupInitiated) {
|
|
26503
|
+
this.clearStoredConversationId();
|
|
26504
|
+
}
|
|
26505
|
+
|
|
26201
26506
|
// Reject all pending data injections on destroy
|
|
26202
26507
|
if (this.pendingInjections.size > 0) {
|
|
26203
26508
|
console.warn("VoiceSDK v2: Rejecting ".concat(this.pendingInjections.size, " pending data injections due to destroy"));
|
|
@@ -27824,6 +28129,7 @@ var AgentSDK = /*#__PURE__*/function () {
|
|
|
27824
28129
|
case 'error':
|
|
27825
28130
|
this.onError(new Error(message.message || message.error || 'Unknown error'));
|
|
27826
28131
|
break;
|
|
28132
|
+
case 'show_items':
|
|
27827
28133
|
case 'show_products':
|
|
27828
28134
|
case 'cart_updated':
|
|
27829
28135
|
case 'add_to_store_cart':
|
|
@@ -28574,190 +28880,99 @@ var ItemCard = /*#__PURE__*/function () {
|
|
|
28574
28880
|
|
|
28575
28881
|
/***/ }),
|
|
28576
28882
|
|
|
28577
|
-
/***/ "./src/widget/
|
|
28883
|
+
/***/ "./src/widget/TTPChatWidget.js":
|
|
28578
28884
|
/*!*************************************!*\
|
|
28579
|
-
!*** ./src/widget/
|
|
28885
|
+
!*** ./src/widget/TTPChatWidget.js ***!
|
|
28580
28886
|
\*************************************/
|
|
28581
28887
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
28582
28888
|
|
|
28583
28889
|
"use strict";
|
|
28584
28890
|
__webpack_require__.r(__webpack_exports__);
|
|
28585
28891
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
28586
|
-
/* harmony export */
|
|
28892
|
+
/* harmony export */ TTPChatWidget: () => (/* binding */ TTPChatWidget)
|
|
28587
28893
|
/* harmony export */ });
|
|
28588
|
-
|
|
28894
|
+
/* harmony import */ var _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core/TextChatSDK.js */ "./src/core/TextChatSDK.js");
|
|
28895
|
+
/* harmony import */ var _VoiceInterface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VoiceInterface.js */ "./src/widget/VoiceInterface.js");
|
|
28896
|
+
/* harmony import */ var _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextInterface.js */ "./src/widget/TextInterface.js");
|
|
28897
|
+
/* harmony import */ var _widget_translations_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./widget-translations.js */ "./src/widget/widget-translations.js");
|
|
28898
|
+
/* harmony import */ var _flavors_index_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../flavors/index.js */ "./src/flavors/index.js");
|
|
28899
|
+
var _excluded = ["agentName"];
|
|
28900
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
28901
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
28902
|
+
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
28903
|
+
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
28904
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
28905
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
28906
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
28907
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
28908
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
28589
28909
|
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
28590
28910
|
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
28591
28911
|
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
28592
28912
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
28593
28913
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
28914
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
28594
28915
|
/**
|
|
28595
|
-
*
|
|
28596
|
-
*
|
|
28597
|
-
* Required from parent (widget):
|
|
28598
|
-
* - config: { landing, header, language, ... }
|
|
28599
|
-
* - translations: object
|
|
28600
|
-
* - shadowRoot: ShadowRoot | Document
|
|
28916
|
+
* TTPChatWidget - Pre-built UI widget for text chat using TextChatSDK
|
|
28917
|
+
* Similar to AgentWidget but designed for text-based chat
|
|
28601
28918
|
*/
|
|
28602
28919
|
|
|
28603
|
-
var LandingScreen = /*#__PURE__*/function () {
|
|
28604
|
-
function LandingScreen(config) {
|
|
28605
|
-
_classCallCheck(this, LandingScreen);
|
|
28606
|
-
this.config = config;
|
|
28607
|
-
this.translations = config.translations || {};
|
|
28608
|
-
this.shadowRoot = config.shadowRoot;
|
|
28609
|
-
}
|
|
28610
|
-
|
|
28611
|
-
/**
|
|
28612
|
-
* Helper to get translated text
|
|
28613
|
-
*/
|
|
28614
|
-
return _createClass(LandingScreen, [{
|
|
28615
|
-
key: "t",
|
|
28616
|
-
value: function t(key) {
|
|
28617
|
-
var lang = this.config.language || 'en';
|
|
28618
|
-
var translations = this.translations[lang] || this.translations.en || {};
|
|
28619
|
-
return translations[key] || key;
|
|
28620
|
-
}
|
|
28621
28920
|
|
|
28622
|
-
/**
|
|
28623
|
-
* Generate HTML for landing screen
|
|
28624
|
-
*/
|
|
28625
|
-
}, {
|
|
28626
|
-
key: "generateHTML",
|
|
28627
|
-
value: function generateHTML() {
|
|
28628
|
-
var landing = this.config.landing || {};
|
|
28629
28921
|
|
|
28630
|
-
// Determine logo content based on logoType
|
|
28631
|
-
var logoContent = '';
|
|
28632
|
-
if (landing.logoType === 'image' && landing.logoImageUrl) {
|
|
28633
|
-
logoContent = "<img src=\"".concat(landing.logoImageUrl, "\" alt=\"Logo\" style=\"max-width: 44px; max-height: 44px; object-fit: contain; border: none; outline: none;\">");
|
|
28634
|
-
} else {
|
|
28635
|
-
logoContent = "<span class=\"landing-avatar-emoji\">".concat(landing.logoIcon || landing.logo || '🤖', "</span>");
|
|
28636
|
-
}
|
|
28637
|
-
return "\n <div class=\"landing-screen\" id=\"landingScreen\">\n <!-- Avatar -->\n <div class=\"landing-avatar\">\n ".concat(logoContent, "\n </div>\n\n <!-- Title -->\n <h2 class=\"landing-title\">").concat(landing.title || this.t('landingTitle'), "</h2>\n <p class=\"landing-subtitle\">").concat(landing.subtitle || this.t('landingSubtitle') || 'Choose your preferred method', "</p>\n\n <!-- Mode Selection - Side by Side -->\n <div class=\"mode-selection\">\n <!-- Voice Call Option -->\n <button class=\"mode-card\" id=\"mode-card-voice\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"/>\n <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.voiceCardTitle || this.t('voiceCall'), "</span>\n </button>\n\n <!-- Text Chat Option -->\n <button class=\"mode-card\" id=\"mode-card-text\">\n <div class=\"mode-card-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\"/>\n </svg>\n </div>\n <span class=\"mode-card-title\">").concat(landing.textCardTitle || this.t('textChat'), "</span>\n </button>\n </div>\n </div>\n ");
|
|
28638
|
-
}
|
|
28639
28922
|
|
|
28640
|
-
/**
|
|
28641
|
-
* Generate CSS for landing screen
|
|
28642
|
-
*/
|
|
28643
|
-
}, {
|
|
28644
|
-
key: "generateCSS",
|
|
28645
|
-
value: function generateCSS() {
|
|
28646
|
-
var landing = this.config.landing || {};
|
|
28647
|
-
var anim = this.config.animation || {};
|
|
28648
28923
|
|
|
28649
|
-
// Add !important when not using Shadow DOM
|
|
28650
|
-
var important = this.config.useShadowDOM === false ? ' !important' : '';
|
|
28651
|
-
return "\n /* ===== LANDING SCREEN - New Design ===== */\n .landing-screen { \n display: none".concat(important, "; \n flex: 1").concat(important, "; \n padding: 32px 24px").concat(important, "; \n background: ").concat(landing.backgroundColor || 'linear-gradient(180deg, #ffffff 0%, rgba(168, 85, 247, 0.03) 100%)', "; \n align-items: center").concat(important, "; \n justify-content: flex-start").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 0").concat(important, "; \n overflow-y: auto").concat(important, "; \n min-height: 0").concat(important, ";\n text-align: center").concat(important, ";\n }\n \n .landing-screen.active { \n display: flex").concat(important, "; \n }\n\n /* Avatar - Richer purple gradient */\n .landing-avatar {\n width: 88px").concat(important, ";\n height: 88px").concat(important, ";\n border-radius: 22px").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n ").concat(function () {
|
|
28652
|
-
// Determine background based on logo type and background settings
|
|
28653
|
-
if (landing.logoType === 'image') {
|
|
28654
|
-
// For image logos, use logoBackgroundColor if enabled, otherwise transparent
|
|
28655
|
-
if (landing.logoBackgroundEnabled !== false) {
|
|
28656
|
-
var bgColor = landing.logoBackgroundColor || landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
|
28657
|
-
return "background: ".concat(bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
|
|
28658
|
-
} else {
|
|
28659
|
-
return "background: transparent; box-shadow: none; border: none; outline: none;";
|
|
28660
|
-
}
|
|
28661
|
-
} else {
|
|
28662
|
-
// For icon logos, use avatarBackground (default behavior)
|
|
28663
|
-
var _bgColor = landing.avatarBackground || 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
|
|
28664
|
-
return "background: ".concat(_bgColor, "; box-shadow: 0 8px 28px rgba(102, 126, 234, 0.35); border: none;");
|
|
28665
|
-
}
|
|
28666
|
-
}(), "\n }\n \n .landing-avatar img {\n border: none !important;\n outline: none !important;\n }\n\n .landing-avatar-emoji {\n font-size: 44px").concat(important, ";\n line-height: 1").concat(important, ";\n }\n\n /* Title & Subtitle */\n .landing-title { \n font-size: 20px").concat(important, "; \n color: ").concat(landing.titleColor || '#1e1b4b', "; \n font-weight: 600").concat(important, "; \n margin-bottom: 6px").concat(important, "; \n text-align: center").concat(important, ";\n line-height: 1.3").concat(important, ";\n }\n\n .landing-subtitle {\n font-size: 14px").concat(important, ";\n color: ").concat(landing.subtitleColor || '#64748b', ";\n margin-bottom: 28px").concat(important, ";\n text-align: center").concat(important, ";\n }\n\n /* Mode Selection - Side by Side */\n .mode-selection { \n display: flex").concat(important, "; \n gap: 12px").concat(important, "; \n width: 100%").concat(important, "; \n justify-content: center").concat(important, "; \n }\n\n .mode-card { \n flex: 1").concat(important, "; \n max-width: 160px").concat(important, "; \n padding: 20px 16px").concat(important, ";\n background: ").concat(landing.modeCardBackgroundColor || '#ffffff', "; \n border: 1px solid ").concat(landing.modeCardBorderColor || 'rgba(0, 0, 0, 0.06)', "; \n border-radius: 18px").concat(important, "; \n cursor: pointer").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n gap: 12px").concat(important, "; \n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, "; \n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06)").concat(important, "; \n font-family: inherit").concat(important, ";\n }\n\n .mode-card:hover { \n transform: translateY(-4px)").concat(important, "; \n box-shadow: 0 8px 24px rgba(124, 58, 237, 0.2)").concat(important, "; \n border-color: rgba(124, 58, 237, 0.3)").concat(important, "; \n }\n\n .mode-card:active {\n transform: translateY(-2px)").concat(important, ";\n }\n\n /* Mode Card Icon - Vibrant purple gradient */\n .mode-card-icon { \n width: 56px").concat(important, "; \n height: 56px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n border-radius: 16px").concat(important, "; \n background: ").concat(landing.modeCardIconBackgroundColor || 'linear-gradient(135deg, #7c3aed, #a855f7)', "; \n color: #fff").concat(important, "; \n box-shadow: 0 4px 14px rgba(124, 58, 237, 0.35)").concat(important, ";\n }\n\n .mode-card-icon svg {\n width: 26px").concat(important, ";\n height: 26px").concat(important, ";\n stroke: white").concat(important, ";\n fill: none").concat(important, ";\n }\n\n .mode-card-title { \n color: ").concat(landing.modeCardTitleColor || '#1e1b4b', "; \n font-weight: 600").concat(important, "; \n font-size: 14px").concat(important, ";\n text-align: center").concat(important, ";\n }\n\n /* Mobile Responsive */\n @media (max-width: 768px) {\n .landing-screen {\n padding: 24px 16px").concat(important, ";\n }\n\n .landing-avatar {\n width: 72px").concat(important, ";\n height: 72px").concat(important, ";\n border-radius: 18px").concat(important, ";\n margin-bottom: 16px").concat(important, ";\n }\n\n .landing-avatar-emoji {\n font-size: 36px").concat(important, ";\n }\n\n .landing-title {\n font-size: 18px").concat(important, ";\n }\n\n .landing-subtitle {\n font-size: 13px").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n }\n\n .mode-selection {\n gap: 10px").concat(important, ";\n }\n\n .mode-card {\n padding: 16px 12px").concat(important, ";\n max-width: 140px").concat(important, ";\n }\n\n .mode-card-icon {\n width: 48px").concat(important, ";\n height: 48px").concat(important, ";\n border-radius: 14px").concat(important, ";\n }\n\n .mode-card-icon svg {\n width: 22px").concat(important, ";\n height: 22px").concat(important, ";\n }\n\n .mode-card-title {\n font-size: 13px").concat(important, ";\n }\n }\n\n @media (max-width: 380px) {\n .mode-selection {\n flex-direction: column").concat(important, ";\n align-items: center").concat(important, ";\n }\n\n .mode-card {\n max-width: 100%").concat(important, ";\n width: 100%").concat(important, ";\n flex-direction: row").concat(important, ";\n padding: 14px 18px").concat(important, ";\n gap: 14px").concat(important, ";\n }\n\n .mode-card-icon {\n flex-shrink: 0").concat(important, ";\n }\n\n .mode-card-title {\n text-align: left").concat(important, ";\n }\n }\n ");
|
|
28667
|
-
}
|
|
28668
28924
|
|
|
28669
|
-
|
|
28670
|
-
|
|
28671
|
-
|
|
28672
|
-
}, {
|
|
28673
|
-
key: "show",
|
|
28674
|
-
value: function show() {
|
|
28675
|
-
var _this$shadowRoot;
|
|
28676
|
-
var landing = (_this$shadowRoot = this.shadowRoot) === null || _this$shadowRoot === void 0 ? void 0 : _this$shadowRoot.getElementById('landingScreen');
|
|
28677
|
-
if (landing) {
|
|
28678
|
-
landing.classList.add('active');
|
|
28679
|
-
}
|
|
28680
|
-
}
|
|
28925
|
+
function isNonEmptyConfigString(v) {
|
|
28926
|
+
return v != null && String(v).trim() !== '';
|
|
28927
|
+
}
|
|
28681
28928
|
|
|
28682
|
-
|
|
28683
|
-
|
|
28684
|
-
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
|
|
28688
|
-
|
|
28689
|
-
|
|
28690
|
-
|
|
28691
|
-
|
|
28692
|
-
|
|
28693
|
-
|
|
28929
|
+
/** True when the integrator set voice start-call colors (not relying on SDK defaults). */
|
|
28930
|
+
function isVoiceStartCallAppearanceCustomized(rawConfig) {
|
|
28931
|
+
var v = rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.voice;
|
|
28932
|
+
if (!v || _typeof(v) !== 'object') return false;
|
|
28933
|
+
var set = function set(k) {
|
|
28934
|
+
return Object.prototype.hasOwnProperty.call(v, k) && isNonEmptyConfigString(v[k]);
|
|
28935
|
+
};
|
|
28936
|
+
return set('primaryBtnGradient1') || set('primaryBtnGradient2') || set('startCallButtonColor');
|
|
28937
|
+
}
|
|
28938
|
+
function computeIsLightPanel(panelBg) {
|
|
28939
|
+
if (!panelBg || panelBg.charAt(0) !== '#') return false;
|
|
28940
|
+
var r = parseInt(panelBg.substr(1, 2), 16);
|
|
28941
|
+
var g = parseInt(panelBg.substr(3, 2), 16);
|
|
28942
|
+
var b = parseInt(panelBg.substr(5, 2), 16);
|
|
28943
|
+
return (r * 299 + g * 587 + b * 114) / 1000 > 160;
|
|
28944
|
+
}
|
|
28694
28945
|
|
|
28695
|
-
/**
|
|
28696
|
-
* Setup event handlers (called by parent widget)
|
|
28697
|
-
*/
|
|
28698
|
-
}, {
|
|
28699
|
-
key: "setupEventHandlers",
|
|
28700
|
-
value: function setupEventHandlers() {
|
|
28701
|
-
var _this$shadowRoot3, _this$shadowRoot4;
|
|
28702
|
-
var callbacks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
28703
|
-
var voiceCard = (_this$shadowRoot3 = this.shadowRoot) === null || _this$shadowRoot3 === void 0 ? void 0 : _this$shadowRoot3.getElementById('mode-card-voice');
|
|
28704
|
-
var textCard = (_this$shadowRoot4 = this.shadowRoot) === null || _this$shadowRoot4 === void 0 ? void 0 : _this$shadowRoot4.getElementById('mode-card-text');
|
|
28705
|
-
if (voiceCard && callbacks.onSelectVoice) {
|
|
28706
|
-
voiceCard.onclick = callbacks.onSelectVoice;
|
|
28707
|
-
}
|
|
28708
|
-
if (textCard && callbacks.onSelectText) {
|
|
28709
|
-
textCard.onclick = callbacks.onSelectText;
|
|
28710
|
-
}
|
|
28711
|
-
}
|
|
28712
|
-
}]);
|
|
28713
|
-
}();
|
|
28714
|
-
|
|
28715
|
-
/***/ }),
|
|
28716
|
-
|
|
28717
|
-
/***/ "./src/widget/TTPChatWidget.js":
|
|
28718
|
-
/*!*************************************!*\
|
|
28719
|
-
!*** ./src/widget/TTPChatWidget.js ***!
|
|
28720
|
-
\*************************************/
|
|
28721
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
28722
|
-
|
|
28723
|
-
"use strict";
|
|
28724
|
-
__webpack_require__.r(__webpack_exports__);
|
|
28725
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
28726
|
-
/* harmony export */ TTPChatWidget: () => (/* binding */ TTPChatWidget)
|
|
28727
|
-
/* harmony export */ });
|
|
28728
|
-
/* harmony import */ var _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../core/TextChatSDK.js */ "./src/core/TextChatSDK.js");
|
|
28729
|
-
/* harmony import */ var _VoiceInterface_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./VoiceInterface.js */ "./src/widget/VoiceInterface.js");
|
|
28730
|
-
/* harmony import */ var _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TextInterface.js */ "./src/widget/TextInterface.js");
|
|
28731
|
-
/* harmony import */ var _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./LandingScreen.js */ "./src/widget/LandingScreen.js");
|
|
28732
|
-
/* harmony import */ var _widget_translations_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./widget-translations.js */ "./src/widget/widget-translations.js");
|
|
28733
|
-
/* harmony import */ var _flavors_index_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../flavors/index.js */ "./src/flavors/index.js");
|
|
28734
|
-
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
28735
|
-
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
28736
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
28737
|
-
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
28738
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
28739
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
28740
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
28741
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
28742
|
-
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
28743
|
-
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
|
|
28744
|
-
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
|
|
28745
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
28746
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
28747
28946
|
/**
|
|
28748
|
-
*
|
|
28749
|
-
* Similar to AgentWidget but designed for text-based chat
|
|
28947
|
+
* Solid CSS color for "TalkToPC" footer link: brand purple by default; matches start-call accent when customized.
|
|
28750
28948
|
*/
|
|
28751
|
-
|
|
28752
|
-
|
|
28753
|
-
|
|
28754
|
-
|
|
28755
|
-
|
|
28756
|
-
|
|
28757
|
-
|
|
28949
|
+
function talkToPcLinkColorForPanel(isLightPanel, mergedVoice, rawConfig, voiceUiEnabled) {
|
|
28950
|
+
var startAccentDark = mergedVoice.primaryBtnGradient1 || mergedVoice.primaryBtnGradient2 || mergedVoice.startCallButtonColor || '#6d56f5';
|
|
28951
|
+
var defaultDark = startAccentDark;
|
|
28952
|
+
var defaultLight = '#7C3AED';
|
|
28953
|
+
var defaults = isLightPanel ? defaultLight : defaultDark;
|
|
28954
|
+
if (!voiceUiEnabled || !isVoiceStartCallAppearanceCustomized(rawConfig)) return defaults;
|
|
28955
|
+
var raw = mergedVoice.primaryBtnGradient1 || mergedVoice.primaryBtnGradient2 || mergedVoice.startCallButtonColor;
|
|
28956
|
+
if (!isNonEmptyConfigString(raw)) return defaults;
|
|
28957
|
+
var t = String(raw).trim();
|
|
28958
|
+
if (t.startsWith('#')) {
|
|
28959
|
+
if (t.length === 4) {
|
|
28960
|
+
var r = t[1];
|
|
28961
|
+
var g = t[2];
|
|
28962
|
+
var b = t[3];
|
|
28963
|
+
return "#".concat(r).concat(r).concat(g).concat(g).concat(b).concat(b);
|
|
28964
|
+
}
|
|
28965
|
+
if (t.length === 7) return t;
|
|
28966
|
+
}
|
|
28967
|
+
var m = t.match(/#[0-9a-fA-F]{6}/i);
|
|
28968
|
+
if (m) return m[0];
|
|
28969
|
+
return defaults;
|
|
28970
|
+
}
|
|
28758
28971
|
var TTPChatWidget = /*#__PURE__*/function () {
|
|
28759
28972
|
function TTPChatWidget() {
|
|
28760
|
-
var _this$config$
|
|
28973
|
+
var _this$config$behavior,
|
|
28974
|
+
_this$config$panel,
|
|
28975
|
+
_this$config$text,
|
|
28761
28976
|
_this$config$text2,
|
|
28762
28977
|
_this$config$voice,
|
|
28763
28978
|
_this$config$voice2,
|
|
@@ -28765,8 +28980,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28765
28980
|
_this$config$voice4,
|
|
28766
28981
|
_this$config$voice5,
|
|
28767
28982
|
_this$config$voice6,
|
|
28768
|
-
_this = this
|
|
28769
|
-
_this$config$behavior2;
|
|
28983
|
+
_this = this;
|
|
28770
28984
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
28771
28985
|
_classCallCheck(this, TTPChatWidget);
|
|
28772
28986
|
this._rawConfig = config;
|
|
@@ -28782,9 +28996,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28782
28996
|
this.sdk = new _core_TextChatSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"](this.config);
|
|
28783
28997
|
this.isOpen = false;
|
|
28784
28998
|
this.isActive = false;
|
|
28785
|
-
this.translations =
|
|
28999
|
+
this.translations = _widget_translations_js__WEBPACK_IMPORTED_MODULE_3__["default"];
|
|
28786
29000
|
// Track current view state in unified mode to prevent resetting when widget is recreated
|
|
28787
|
-
this.currentView = '
|
|
29001
|
+
this.currentView = 'voice'; // 'text' or 'voice' (unified home is always voice hero)
|
|
28788
29002
|
// Race condition prevention: prevent multiple rapid clicks on Voice Call button
|
|
28789
29003
|
this.isStartingCall = false;
|
|
28790
29004
|
// Shadow DOM root for CSS isolation
|
|
@@ -28807,7 +29021,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28807
29021
|
|
|
28808
29022
|
// Initialize interfaces with proper config (after shadow root is created)
|
|
28809
29023
|
// Voice interface needs voice config merged with main config
|
|
29024
|
+
var widgetModeForVoice = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) || 'unified';
|
|
29025
|
+
var showVoiceUi = widgetModeForVoice === 'unified' || widgetModeForVoice === 'voice-only';
|
|
29026
|
+
var panelBgForBrand = ((_this$config$panel = this.config.panel) === null || _this$config$panel === void 0 ? void 0 : _this$config$panel.backgroundColor) || '#16161e';
|
|
29027
|
+
var talkToPcLink = talkToPcLinkColorForPanel(computeIsLightPanel(panelBgForBrand), this.config.voice, this._rawConfig, showVoiceUi);
|
|
28810
29028
|
var voiceConfig = _objectSpread(_objectSpread(_objectSpread({}, this.config), this.config.voice), {}, {
|
|
29029
|
+
agentName: this.config.agentName,
|
|
29030
|
+
_talkToPcLinkColor: talkToPcLink,
|
|
28811
29031
|
// Pass through text input placeholder for voice text input
|
|
28812
29032
|
inputPlaceholder: ((_this$config$text = this.config.text) === null || _this$config$text === void 0 ? void 0 : _this$config$text.inputPlaceholder) || this.config.inputPlaceholder || 'Type your message...',
|
|
28813
29033
|
// Pass through send button color for voice send button
|
|
@@ -28835,15 +29055,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28835
29055
|
onAudioStoppedPlaying: this.config.onAudioStoppedPlaying,
|
|
28836
29056
|
onSubtitleDisplay: this.config.onSubtitleDisplay,
|
|
28837
29057
|
onVoiceCallButtonClick: this.config.onVoiceCallButtonClick,
|
|
28838
|
-
// Callback when call ends
|
|
28839
|
-
// BUT: Don't
|
|
29058
|
+
// Callback when call ends — return to unified home (voice hero), not legacy mode picker
|
|
29059
|
+
// BUT: Don't switch views if we're showing a domain error
|
|
28840
29060
|
onCallEnd: function onCallEnd() {
|
|
28841
|
-
var _this$config$
|
|
29061
|
+
var _this$config$behavior2;
|
|
28842
29062
|
if (_this._isDomainErrorVisible()) {
|
|
28843
|
-
console.log('🚫 Domain error is displayed - NOT returning to
|
|
29063
|
+
console.log('🚫 Domain error is displayed - NOT returning to home from onCallEnd');
|
|
28844
29064
|
return;
|
|
28845
29065
|
}
|
|
28846
|
-
var widgetMode = ((_this$config$
|
|
29066
|
+
var widgetMode = ((_this$config$behavior2 = _this.config.behavior) === null || _this$config$behavior2 === void 0 ? void 0 : _this$config$behavior2.mode) || 'unified';
|
|
28847
29067
|
if (widgetMode === 'unified') {
|
|
28848
29068
|
if (window.innerWidth <= 768) {
|
|
28849
29069
|
var _this$shadowRoot, _this$shadowRoot2;
|
|
@@ -28863,7 +29083,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28863
29083
|
onShowVoice: function onShowVoice() {
|
|
28864
29084
|
_this.showVoice();
|
|
28865
29085
|
},
|
|
28866
|
-
// Callback to show
|
|
29086
|
+
// Callback to show unified home (voice hero; used by domain error back button)
|
|
28867
29087
|
onShowLanding: function onShowLanding() {
|
|
28868
29088
|
_this.showLanding();
|
|
28869
29089
|
},
|
|
@@ -28883,18 +29103,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28883
29103
|
});
|
|
28884
29104
|
this.textInterface = new _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__.TextInterface(textConfig, this.sdk);
|
|
28885
29105
|
|
|
28886
|
-
// Landing screen (only for unified mode)
|
|
28887
|
-
var widgetMode = ((_this$config$behavior2 = this.config.behavior) === null || _this$config$behavior2 === void 0 ? void 0 : _this$config$behavior2.mode) || 'unified';
|
|
28888
|
-
if (widgetMode === 'unified') {
|
|
28889
|
-
var landingConfig = _objectSpread(_objectSpread({}, this.config), {}, {
|
|
28890
|
-
translations: this.translations,
|
|
28891
|
-
shadowRoot: this.shadowRoot
|
|
28892
|
-
});
|
|
28893
|
-
this.landingScreen = new _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__.LandingScreen(landingConfig);
|
|
28894
|
-
} else {
|
|
28895
|
-
this.landingScreen = null;
|
|
28896
|
-
}
|
|
28897
|
-
|
|
28898
29106
|
// Now create widget HTML and populate shadow root
|
|
28899
29107
|
this.createWidget();
|
|
28900
29108
|
this.setupEventHandlers();
|
|
@@ -28998,7 +29206,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
28998
29206
|
value: function _initFlavor(flavorName) {
|
|
28999
29207
|
var _this$_flavorObj,
|
|
29000
29208
|
_this3 = this;
|
|
29001
|
-
var factory = (0,
|
|
29209
|
+
var factory = (0,_flavors_index_js__WEBPACK_IMPORTED_MODULE_4__.loadFlavor)(flavorName);
|
|
29002
29210
|
if (!factory) {
|
|
29003
29211
|
console.error("[TTPChatWidget] Unknown flavor: \"".concat(flavorName, "\". Available flavors: ecommerce. Widget will run in vanilla mode."));
|
|
29004
29212
|
return;
|
|
@@ -29064,6 +29272,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29064
29272
|
}
|
|
29065
29273
|
}
|
|
29066
29274
|
|
|
29275
|
+
/**
|
|
29276
|
+
* Resolved direction for widget chrome (shadow host, launcher). After mergeWithDefaults,
|
|
29277
|
+
* config.direction is always 'ltr' or 'rtl'.
|
|
29278
|
+
*/
|
|
29279
|
+
}, {
|
|
29280
|
+
key: "getEffectiveTextDirection",
|
|
29281
|
+
value: function getEffectiveTextDirection() {
|
|
29282
|
+
var _this$config;
|
|
29283
|
+
return ((_this$config = this.config) === null || _this$config === void 0 ? void 0 : _this$config.direction) === 'rtl' ? 'rtl' : 'ltr';
|
|
29284
|
+
}
|
|
29285
|
+
|
|
29067
29286
|
/**
|
|
29068
29287
|
* Open the widget
|
|
29069
29288
|
*/
|
|
@@ -29086,7 +29305,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29086
29305
|
}, {
|
|
29087
29306
|
key: "mergeWithDefaults",
|
|
29088
29307
|
value: function mergeWithDefaults(userConfig) {
|
|
29089
|
-
var _userConfig$button, _userConfig$button2, _userConfig$icon, _userConfig$icon2, _userConfig$icon3, _userConfig$icon4, _userConfig$icon5, _userConfig$
|
|
29308
|
+
var _userConfig$button, _userConfig$button2, _userConfig$icon, _userConfig$icon2, _userConfig$icon3, _userConfig$icon4, _userConfig$icon5, _userConfig$button3, _userConfig$button4, _userConfig$button5, _userConfig$icon7, _userConfig$button6, _userConfig$button7, _userConfig$button8, _userConfig$button9, _userConfig$icon8, _userConfig$panel, _userConfig$panel2, _userConfig$panel3, _userConfig$panel4, _userConfig$panel5, _userConfig$panel6, _userConfig$text, _userConfig$panel11, _userConfig$text2, _userConfig$panel12, _userConfig$text3, _userConfig$panel13, _userConfig$text4, _userConfig$panel14, _userConfig$text5, _userConfig$panel15, _userConfig$text6, _userConfig$panel16, _userConfig$text7, _userConfig$panel17, _userConfig$text8, _userConfig$panel18, _userConfig$text9, _userConfig$panel19, _userConfig$text0, _userConfig$panel20, _userConfig$text1, _userConfig$panel21, _userConfig$text10, _userConfig$panel22, _userConfig$text11, _userConfig$panel23, _userConfig$text12, _userConfig$panel24, _userConfig$text13, _userConfig$panel25, _userConfig$text14, _userConfig$panel26, _userConfig$text15, _userConfig$panel27, _userConfig$text16, _userConfig$panel28, _userConfig$text17, _userConfig$panel29, _userConfig$footer, _userConfig$footer2, _userConfig$footer3, _userConfig$footer4, _userConfig$tooltips, _userConfig$tooltips2, _userConfig$tooltips3, _userConfig$tooltips4, _userConfig$tooltips5, _userConfig$tooltips6, _userConfig$messages, _userConfig$messages2, _userConfig$messages3, _userConfig$messages4, _userConfig$messages5, _userConfig$messages6, _userConfig$messages7, _userConfig$messages8, _userConfig$messages9, _userConfig$messages0, _userConfig$messages1, _userConfig$messages10, _userConfig$messages11, _userConfig$animation, _userConfig$animation2, _userConfig$animation3, _userConfig$animation4, _userConfig$promptAni, _userConfig$promptAni2, _userConfig$promptAni3, _userConfig$promptAni4, _userConfig$promptAni5, _userConfig$promptAni6, _userConfig$promptAni7, _userConfig$promptAni8, _userConfig$promptAni9, _userConfig$promptAni0, _userConfig$behavior, _userConfig$behavior2, _userConfig$behavior3, _userConfig$behavior4, _userConfig$behavior5, _userConfig$behavior6, _userConfig$behavior7, _userConfig$behavior8, _userConfig$accessibi, _userConfig$accessibi2, _userConfig$accessibi3;
|
|
29090
29309
|
// Handle legacy position string format
|
|
29091
29310
|
var positionConfig = userConfig.position || 'bottom-right';
|
|
29092
29311
|
if (typeof positionConfig === 'string') {
|
|
@@ -29130,7 +29349,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29130
29349
|
}
|
|
29131
29350
|
});
|
|
29132
29351
|
}
|
|
29133
|
-
return _objectSpread({
|
|
29352
|
+
return _objectSpread(_objectSpread({
|
|
29134
29353
|
// Required (agentId is required, appId is optional)
|
|
29135
29354
|
agentId: userConfig.agentId,
|
|
29136
29355
|
appId: userConfig.appId,
|
|
@@ -29138,22 +29357,35 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29138
29357
|
// signedUrl accepted as backward-compat alias
|
|
29139
29358
|
agentSettingsOverride: userConfig.agentSettingsOverride,
|
|
29140
29359
|
demo: userConfig.demo !== false,
|
|
29141
|
-
direction:
|
|
29142
|
-
|
|
29143
|
-
|
|
29144
|
-
|
|
29145
|
-
|
|
29360
|
+
direction: function () {
|
|
29361
|
+
if (userConfig.direction === 'rtl' || userConfig.direction === 'ltr') {
|
|
29362
|
+
return userConfig.direction;
|
|
29363
|
+
}
|
|
29364
|
+
var langBase = String(userConfig.language || 'en').toLowerCase().split(/[-_]/)[0];
|
|
29365
|
+
if (langBase === 'he' || langBase === 'ar') return 'rtl';
|
|
29366
|
+
return 'ltr';
|
|
29367
|
+
}(),
|
|
29368
|
+
language: userConfig.language || 'en'
|
|
29369
|
+
}, isNonEmptyConfigString(userConfig.agentName) ? {
|
|
29370
|
+
agentName: String(userConfig.agentName).trim()
|
|
29371
|
+
} : {}), {}, {
|
|
29146
29372
|
// Icon/Image Configuration
|
|
29147
|
-
icon: _objectSpread({
|
|
29373
|
+
icon: _objectSpread(_objectSpread({
|
|
29148
29374
|
type: ((_userConfig$icon = userConfig.icon) === null || _userConfig$icon === void 0 ? void 0 : _userConfig$icon.type) || 'custom',
|
|
29149
29375
|
// 'microphone', 'custom', 'emoji', 'text'
|
|
29150
|
-
|
|
29151
|
-
|
|
29152
|
-
|
|
29153
|
-
size: ((_userConfig$icon5 = userConfig.icon) === null || _userConfig$icon5 === void 0 ? void 0 : _userConfig$icon5.size) || 'medium',
|
|
29376
|
+
emoji: ((_userConfig$icon2 = userConfig.icon) === null || _userConfig$icon2 === void 0 ? void 0 : _userConfig$icon2.emoji) || '🎤',
|
|
29377
|
+
text: ((_userConfig$icon3 = userConfig.icon) === null || _userConfig$icon3 === void 0 ? void 0 : _userConfig$icon3.text) || 'AI',
|
|
29378
|
+
size: ((_userConfig$icon4 = userConfig.icon) === null || _userConfig$icon4 === void 0 ? void 0 : _userConfig$icon4.size) || 'medium',
|
|
29154
29379
|
// 'small', 'medium', 'large', 'xl'
|
|
29155
|
-
backgroundColor: ((_userConfig$
|
|
29156
|
-
}, userConfig.icon),
|
|
29380
|
+
backgroundColor: ((_userConfig$icon5 = userConfig.icon) === null || _userConfig$icon5 === void 0 ? void 0 : _userConfig$icon5.backgroundColor) || '#FFFFFF'
|
|
29381
|
+
}, userConfig.icon), {}, {
|
|
29382
|
+
/* After spread: empty / omitted URL → null so desktop pill uses waveform like mobile FAB */
|
|
29383
|
+
customImage: function (_userConfig$icon6) {
|
|
29384
|
+
var v = (_userConfig$icon6 = userConfig.icon) === null || _userConfig$icon6 === void 0 ? void 0 : _userConfig$icon6.customImage;
|
|
29385
|
+
if (v == null || String(v).trim() === '') return null;
|
|
29386
|
+
return String(v).trim();
|
|
29387
|
+
}()
|
|
29388
|
+
}),
|
|
29157
29389
|
// Positioning Configuration (supports both object and legacy string)
|
|
29158
29390
|
position: _objectSpread({
|
|
29159
29391
|
vertical: positionConfig.vertical || 'bottom',
|
|
@@ -29185,38 +29417,46 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29185
29417
|
backdropFilter: ((_userConfig$panel5 = userConfig.panel) === null || _userConfig$panel5 === void 0 ? void 0 : _userConfig$panel5.backdropFilter) || null,
|
|
29186
29418
|
border: ((_userConfig$panel6 = userConfig.panel) === null || _userConfig$panel6 === void 0 ? void 0 : _userConfig$panel6.border) || '1px solid #E5E7EB'
|
|
29187
29419
|
}, userConfig.panel),
|
|
29188
|
-
// Voice-specific Configuration
|
|
29189
|
-
voice:
|
|
29190
|
-
|
|
29191
|
-
|
|
29192
|
-
|
|
29193
|
-
|
|
29194
|
-
|
|
29195
|
-
|
|
29196
|
-
|
|
29197
|
-
|
|
29198
|
-
|
|
29199
|
-
|
|
29200
|
-
|
|
29201
|
-
|
|
29202
|
-
|
|
29203
|
-
|
|
29204
|
-
|
|
29205
|
-
|
|
29206
|
-
|
|
29207
|
-
|
|
29208
|
-
|
|
29209
|
-
|
|
29210
|
-
|
|
29211
|
-
|
|
29212
|
-
|
|
29213
|
-
|
|
29214
|
-
|
|
29215
|
-
|
|
29216
|
-
|
|
29217
|
-
|
|
29218
|
-
|
|
29219
|
-
|
|
29420
|
+
// Voice-specific Configuration (`voice.agentName` is ignored — use root `agentName`)
|
|
29421
|
+
voice: function (_userConfig$voice, _userConfig$panel7, _userConfig$voice2, _userConfig$panel8, _userConfig$voice3, _userConfig$panel9, _userConfig$voice4, _userConfig$panel0, _userConfig$voice5, _userConfig$panel1, _userConfig$voice6, _userConfig$panel10, _userConfig$voice7, _userConfig$voice8, _userConfig$voice9, _userConfig$voice0, _userConfig$voice1, _userConfig$voice10, _userConfig$voice11, _userConfig$voice12, _userConfig$voice13, _userConfig$voice14, _userConfig$voice15, _userConfig$voice16, _userConfig$voice17, _userConfig$voice18, _userConfig$voice$use, _userConfig$voice19, _userConfig$voice20, _userConfig$voice21, _userConfig$voice22, _userConfig$voice23, _userConfig$voice24) {
|
|
29422
|
+
var voiceOut = _objectSpread(_objectSpread({
|
|
29423
|
+
// Voice button colors (inside panel)
|
|
29424
|
+
micButtonColor: ((_userConfig$voice = userConfig.voice) === null || _userConfig$voice === void 0 ? void 0 : _userConfig$voice.micButtonColor) || ((_userConfig$panel7 = userConfig.panel) === null || _userConfig$panel7 === void 0 ? void 0 : _userConfig$panel7.micButtonColor) || primaryColor,
|
|
29425
|
+
micButtonActiveColor: ((_userConfig$voice2 = userConfig.voice) === null || _userConfig$voice2 === void 0 ? void 0 : _userConfig$voice2.micButtonActiveColor) || ((_userConfig$panel8 = userConfig.panel) === null || _userConfig$panel8 === void 0 ? void 0 : _userConfig$panel8.micButtonActiveColor) || '#EF4444',
|
|
29426
|
+
// Voice button hint text (below button)
|
|
29427
|
+
micButtonHint: _objectSpread(_objectSpread({
|
|
29428
|
+
text: ((_userConfig$voice3 = userConfig.voice) === null || _userConfig$voice3 === void 0 || (_userConfig$voice3 = _userConfig$voice3.micButtonHint) === null || _userConfig$voice3 === void 0 ? void 0 : _userConfig$voice3.text) || ((_userConfig$panel9 = userConfig.panel) === null || _userConfig$panel9 === void 0 || (_userConfig$panel9 = _userConfig$panel9.micButtonHint) === null || _userConfig$panel9 === void 0 ? void 0 : _userConfig$panel9.text) || 'Click the button to start voice conversation',
|
|
29429
|
+
color: ((_userConfig$voice4 = userConfig.voice) === null || _userConfig$voice4 === void 0 || (_userConfig$voice4 = _userConfig$voice4.micButtonHint) === null || _userConfig$voice4 === void 0 ? void 0 : _userConfig$voice4.color) || ((_userConfig$panel0 = userConfig.panel) === null || _userConfig$panel0 === void 0 || (_userConfig$panel0 = _userConfig$panel0.micButtonHint) === null || _userConfig$panel0 === void 0 ? void 0 : _userConfig$panel0.color) || '#6B7280',
|
|
29430
|
+
fontSize: ((_userConfig$voice5 = userConfig.voice) === null || _userConfig$voice5 === void 0 || (_userConfig$voice5 = _userConfig$voice5.micButtonHint) === null || _userConfig$voice5 === void 0 ? void 0 : _userConfig$voice5.fontSize) || ((_userConfig$panel1 = userConfig.panel) === null || _userConfig$panel1 === void 0 || (_userConfig$panel1 = _userConfig$panel1.micButtonHint) === null || _userConfig$panel1 === void 0 ? void 0 : _userConfig$panel1.fontSize) || '12px'
|
|
29431
|
+
}, (_userConfig$voice6 = userConfig.voice) === null || _userConfig$voice6 === void 0 ? void 0 : _userConfig$voice6.micButtonHint), (_userConfig$panel10 = userConfig.panel) === null || _userConfig$panel10 === void 0 ? void 0 : _userConfig$panel10.micButtonHint),
|
|
29432
|
+
// Voice interface colors
|
|
29433
|
+
avatarBackgroundColor: ((_userConfig$voice7 = userConfig.voice) === null || _userConfig$voice7 === void 0 ? void 0 : _userConfig$voice7.avatarBackgroundColor) || '#667eea',
|
|
29434
|
+
avatarActiveBackgroundColor: ((_userConfig$voice8 = userConfig.voice) === null || _userConfig$voice8 === void 0 ? void 0 : _userConfig$voice8.avatarActiveBackgroundColor) || '#667eea',
|
|
29435
|
+
statusTitleColor: ((_userConfig$voice9 = userConfig.voice) === null || _userConfig$voice9 === void 0 ? void 0 : _userConfig$voice9.statusTitleColor) || '#1e293b',
|
|
29436
|
+
statusSubtitleColor: ((_userConfig$voice0 = userConfig.voice) === null || _userConfig$voice0 === void 0 ? void 0 : _userConfig$voice0.statusSubtitleColor) || '#64748b',
|
|
29437
|
+
statusDotColor: ((_userConfig$voice1 = userConfig.voice) === null || _userConfig$voice1 === void 0 ? void 0 : _userConfig$voice1.statusDotColor) || '#10b981',
|
|
29438
|
+
statusText: ((_userConfig$voice10 = userConfig.voice) === null || _userConfig$voice10 === void 0 ? void 0 : _userConfig$voice10.statusText) || null,
|
|
29439
|
+
startCallButtonColor: ((_userConfig$voice11 = userConfig.voice) === null || _userConfig$voice11 === void 0 ? void 0 : _userConfig$voice11.startCallButtonColor) || '#667eea',
|
|
29440
|
+
startCallButtonTextColor: ((_userConfig$voice12 = userConfig.voice) === null || _userConfig$voice12 === void 0 ? void 0 : _userConfig$voice12.startCallButtonTextColor) || '#FFFFFF',
|
|
29441
|
+
startCallTitle: ((_userConfig$voice13 = userConfig.voice) === null || _userConfig$voice13 === void 0 ? void 0 : _userConfig$voice13.startCallTitle) || null,
|
|
29442
|
+
startCallSubtitle: ((_userConfig$voice14 = userConfig.voice) === null || _userConfig$voice14 === void 0 ? void 0 : _userConfig$voice14.startCallSubtitle) || null,
|
|
29443
|
+
startCallButtonText: ((_userConfig$voice15 = userConfig.voice) === null || _userConfig$voice15 === void 0 ? void 0 : _userConfig$voice15.startCallButtonText) || null,
|
|
29444
|
+
transcriptBackgroundColor: ((_userConfig$voice16 = userConfig.voice) === null || _userConfig$voice16 === void 0 ? void 0 : _userConfig$voice16.transcriptBackgroundColor) || '#FFFFFF',
|
|
29445
|
+
transcriptTextColor: ((_userConfig$voice17 = userConfig.voice) === null || _userConfig$voice17 === void 0 ? void 0 : _userConfig$voice17.transcriptTextColor) || '#1e293b',
|
|
29446
|
+
transcriptLabelColor: ((_userConfig$voice18 = userConfig.voice) === null || _userConfig$voice18 === void 0 ? void 0 : _userConfig$voice18.transcriptLabelColor) || '#94a3b8',
|
|
29447
|
+
// Live user STT line prefix (e.g. "You: "). null = use translation userTranscriptPrefix; '' = no prefix
|
|
29448
|
+
userTranscriptPrefix: (_userConfig$voice$use = (_userConfig$voice19 = userConfig.voice) === null || _userConfig$voice19 === void 0 ? void 0 : _userConfig$voice19.userTranscriptPrefix) !== null && _userConfig$voice$use !== void 0 ? _userConfig$voice$use : null,
|
|
29449
|
+
controlButtonColor: ((_userConfig$voice20 = userConfig.voice) === null || _userConfig$voice20 === void 0 ? void 0 : _userConfig$voice20.controlButtonColor) || '#FFFFFF',
|
|
29450
|
+
controlButtonSecondaryColor: ((_userConfig$voice21 = userConfig.voice) === null || _userConfig$voice21 === void 0 ? void 0 : _userConfig$voice21.controlButtonSecondaryColor) || '#64748b',
|
|
29451
|
+
endCallButtonColor: ((_userConfig$voice22 = userConfig.voice) === null || _userConfig$voice22 === void 0 ? void 0 : _userConfig$voice22.endCallButtonColor) || '#ef4444',
|
|
29452
|
+
// Voice language setting
|
|
29453
|
+
language: ((_userConfig$voice23 = userConfig.voice) === null || _userConfig$voice23 === void 0 ? void 0 : _userConfig$voice23.language) || userConfig.language || 'en'
|
|
29454
|
+
}, userConfig.voice), isNonEmptyConfigString(userConfig.headerAvatarImageUrl) && !isNonEmptyConfigString((_userConfig$voice24 = userConfig.voice) === null || _userConfig$voice24 === void 0 ? void 0 : _userConfig$voice24.headerAvatarImageUrl) ? {
|
|
29455
|
+
headerAvatarImageUrl: String(userConfig.headerAvatarImageUrl).trim()
|
|
29456
|
+
} : {});
|
|
29457
|
+
delete voiceOut.agentName;
|
|
29458
|
+
return voiceOut;
|
|
29459
|
+
}(),
|
|
29220
29460
|
// Text-specific Configuration
|
|
29221
29461
|
text: _objectSpread({
|
|
29222
29462
|
// Send button colors (inside panel)
|
|
@@ -29314,8 +29554,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29314
29554
|
backgroundColor: cleanHeaderConfig.backgroundColor || '#7C3AED',
|
|
29315
29555
|
// Default purple
|
|
29316
29556
|
textColor: cleanHeaderConfig.textColor || '#FFFFFF',
|
|
29317
|
-
showCloseButton: cleanHeaderConfig.showCloseButton !== false
|
|
29318
|
-
mobileLabel: cleanHeaderConfig.mobileLabel || 'Chat'
|
|
29557
|
+
showCloseButton: cleanHeaderConfig.showCloseButton !== false
|
|
29319
29558
|
}, cleanHeaderConfig);
|
|
29320
29559
|
return finalHeader;
|
|
29321
29560
|
}(),
|
|
@@ -29386,9 +29625,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29386
29625
|
autoConnect: ((_userConfig$behavior4 = userConfig.behavior) === null || _userConfig$behavior4 === void 0 ? void 0 : _userConfig$behavior4.autoConnect) || false,
|
|
29387
29626
|
showWelcomeMessage: ((_userConfig$behavior5 = userConfig.behavior) === null || _userConfig$behavior5 === void 0 ? void 0 : _userConfig$behavior5.showWelcomeMessage) !== false,
|
|
29388
29627
|
welcomeMessage: ((_userConfig$behavior6 = userConfig.behavior) === null || _userConfig$behavior6 === void 0 ? void 0 : _userConfig$behavior6.welcomeMessage) || 'Hello! How can I help you today?',
|
|
29389
|
-
// Voice selection landing (enabled by default)
|
|
29390
29628
|
enableVoiceMode: ((_userConfig$behavior7 = userConfig.behavior) === null || _userConfig$behavior7 === void 0 ? void 0 : _userConfig$behavior7.enableVoiceMode) !== undefined ? userConfig.behavior.enableVoiceMode : true,
|
|
29391
|
-
// Widget mode: 'unified' (
|
|
29629
|
+
// Widget mode: 'unified' (voice hero + text chat in panel; mobile pre-chat overlay), 'voice-only', 'text-only'
|
|
29392
29630
|
mode: ((_userConfig$behavior8 = userConfig.behavior) === null || _userConfig$behavior8 === void 0 ? void 0 : _userConfig$behavior8.mode) || 'unified'
|
|
29393
29631
|
}, userConfig.behavior),
|
|
29394
29632
|
// Accessibility Configuration
|
|
@@ -29470,6 +29708,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29470
29708
|
// The actual button and panel have pointer-events: auto to receive clicks
|
|
29471
29709
|
// Using width/height 100% ensures fixed-position children have proper containing block
|
|
29472
29710
|
host.style.cssText = 'position: fixed; z-index: 10000; pointer-events: none; top: 0; left: 0; width: 100%; height: 100%; overflow: visible;';
|
|
29711
|
+
host.setAttribute('dir', this.getEffectiveTextDirection());
|
|
29473
29712
|
|
|
29474
29713
|
// Attach shadow DOM
|
|
29475
29714
|
this.shadowRoot = host.attachShadow({
|
|
@@ -29498,6 +29737,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29498
29737
|
// Container covers viewport but is click-through (pointer-events: none)
|
|
29499
29738
|
// The actual button and panel have pointer-events: auto to receive clicks
|
|
29500
29739
|
container.style.cssText = 'position: fixed; z-index: 10000; pointer-events: none; top: 0; left: 0; width: 100%; height: 100%; overflow: visible;';
|
|
29740
|
+
container.setAttribute('dir', this.getEffectiveTextDirection());
|
|
29501
29741
|
|
|
29502
29742
|
// Append container to body
|
|
29503
29743
|
document.body.appendChild(container);
|
|
@@ -29529,7 +29769,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29529
29769
|
resetCSS = "\n :host {\n all: initial".concat(important, ";\n display: block").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n img {\n max-width: none !important;\n }\n #text-chat-button img {\n width: 22px !important;\n height: 22px !important;\n }\n #text-chat-button {\n pointer-events: auto").concat(important, ";\n }\n #text-chat-panel {\n pointer-events: auto").concat(important, ";\n }\n .ttp-mobile-fab {\n pointer-events: auto").concat(important, ";\n }\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n ");
|
|
29530
29770
|
} else {
|
|
29531
29771
|
// Regular DOM mode - targeted reset without breaking widget styles
|
|
29532
|
-
resetCSS = "\n /* Reset only problematic inherited styles, not all styles */\n #text-chat-button,\n #text-chat-panel,\n #text-chat-panel * {\n box-sizing: border-box".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n }\n \n /* Theme often sets img { max-width: 100% } which squashes widget art.\n Do NOT set width/height: auto on all #text-chat-panel img \u2014 that uses\n !important and overrides ecommerce card images (.ttp-product-image img\n needs width/height 100% + object-fit), which shows as empty/blank tiles. */\n #text-chat-panel img {\n max-width: none").concat(important, ";\n }\n \n #text-chat-button img {\n max-width: none").concat(important, ";\n width: 22px !important;\n height: 22px !important;\n }\n \n /* Ensure button and panel can receive clicks */\n #text-chat-button,\n #text-chat-panel,\n .ttp-mobile-fab,\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left").concat(important, ";\n line-height: normal").concat(important, ";\n letter-spacing: normal").concat(important, ";\n word-spacing: normal").concat(important, ";\n text-transform: none").concat(important, ";\n text-indent: 0").concat(important, ";\n text-shadow: none").concat(important, ";\n white-space: normal").concat(important, ";\n }\n \n /* Flex layout for shell only \u2014 do NOT force display on .
|
|
29772
|
+
resetCSS = "\n /* Reset only problematic inherited styles, not all styles */\n #text-chat-button,\n #text-chat-panel,\n #text-chat-panel * {\n box-sizing: border-box".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n }\n \n /* Theme often sets img { max-width: 100% } which squashes widget art.\n Do NOT set width/height: auto on all #text-chat-panel img \u2014 that uses\n !important and overrides ecommerce card images (.ttp-product-image img\n needs width/height 100% + object-fit), which shows as empty/blank tiles. */\n #text-chat-panel img {\n max-width: none").concat(important, ";\n }\n \n #text-chat-button img {\n max-width: none").concat(important, ";\n width: 22px !important;\n height: 22px !important;\n }\n \n /* Ensure button and panel can receive clicks */\n #text-chat-button,\n #text-chat-panel,\n .ttp-mobile-fab,\n #ttpMobileLanding {\n pointer-events: auto").concat(important, ";\n }\n \n /* Reset any inherited text styles that might break layout */\n #text-chat-panel {\n text-align: left").concat(important, ";\n line-height: normal").concat(important, ";\n letter-spacing: normal").concat(important, ";\n word-spacing: normal").concat(important, ";\n text-transform: none").concat(important, ";\n text-indent: 0").concat(important, ";\n text-shadow: none").concat(important, ";\n white-space: normal").concat(important, ";\n }\n \n /* Flex layout for shell only \u2014 do NOT force display on .voice-interface /\n .text-interface: #text-chat-panel + class beats component rules and keeps\n both visible (breaks Shopify / useShadowDOM: false). */\n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container,\n #text-chat-panel .widget-header {\n display: flex").concat(important, ";\n }\n \n #text-chat-panel .widget-shell,\n #text-chat-panel .panel-inner,\n #text-chat-panel .widget-container {\n flex-direction: column").concat(important, ";\n }\n \n /* Ensure proper stacking */\n #text-chat-button {\n z-index: 10001 !important;\n }\n \n #text-chat-panel {\n z-index: 10000 !important;\n }\n ");
|
|
29533
29773
|
}
|
|
29534
29774
|
var widgetHTML = this.generateWidgetHTML();
|
|
29535
29775
|
if (this.config.useShadowDOM) {
|
|
@@ -29543,12 +29783,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29543
29783
|
}
|
|
29544
29784
|
this.setupWidgetEvents();
|
|
29545
29785
|
|
|
29546
|
-
// On desktop,
|
|
29547
|
-
if (window.innerWidth > 768
|
|
29786
|
+
// On desktop, ensure voice hero is shown for unified/voice-only (in-panel mode picker removed)
|
|
29787
|
+
if (window.innerWidth > 768) {
|
|
29548
29788
|
var _this$config$behavior3;
|
|
29549
29789
|
var widgetMode = ((_this$config$behavior3 = this.config.behavior) === null || _this$config$behavior3 === void 0 ? void 0 : _this$config$behavior3.mode) || 'unified';
|
|
29550
|
-
var
|
|
29551
|
-
if (
|
|
29790
|
+
var preferVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
|
|
29791
|
+
if (preferVoice && this.currentView !== 'text') {
|
|
29552
29792
|
this.showVoice();
|
|
29553
29793
|
}
|
|
29554
29794
|
}
|
|
@@ -29644,8 +29884,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29644
29884
|
key: "generateWidgetHTML",
|
|
29645
29885
|
value: function generateWidgetHTML() {
|
|
29646
29886
|
var _this$config$behavior4,
|
|
29647
|
-
_this6 = this
|
|
29648
|
-
_this$config$icon2;
|
|
29887
|
+
_this6 = this;
|
|
29649
29888
|
var pos = this.config.position;
|
|
29650
29889
|
var btn = this.config.button;
|
|
29651
29890
|
var icon = this.config.icon;
|
|
@@ -29673,11 +29912,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29673
29912
|
|
|
29674
29913
|
// Generate position styles
|
|
29675
29914
|
var positionStyles = this.generatePositionStyles();
|
|
29676
|
-
|
|
29677
|
-
// Generate icon HTML
|
|
29678
|
-
var iconHTML = this.generateIconHTML(iconSize);
|
|
29679
29915
|
var widgetMode = ((_this$config$behavior4 = this.config.behavior) === null || _this$config$behavior4 === void 0 ? void 0 : _this$config$behavior4.mode) || 'unified';
|
|
29680
|
-
var showLanding = widgetMode === 'unified';
|
|
29681
29916
|
var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
|
|
29682
29917
|
var showText = widgetMode === 'unified' || widgetMode === 'text-only';
|
|
29683
29918
|
var voiceEnabled = showVoice;
|
|
@@ -29721,7 +29956,15 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29721
29956
|
isPromptEnabled: isPromptEnabled,
|
|
29722
29957
|
willGenerateHTML: !!promptBubbleHTML
|
|
29723
29958
|
});
|
|
29724
|
-
|
|
29959
|
+
var pillTitle = header.pillTitle != null && String(header.pillTitle).trim() !== '' ? String(header.pillTitle).trim() : header.title || 'Assistant';
|
|
29960
|
+
/* Mobile FAB: optional header.mobileLabel; otherwise same main line as desktop pill (pillTitle). Not header.mobileLabel default 'Chat' — that hid pillTitle. */
|
|
29961
|
+
var mobileFabLabel = header.mobileLabel != null && String(header.mobileLabel).trim() !== '' ? String(header.mobileLabel).trim() : pillTitle;
|
|
29962
|
+
var mobileLandingHeroName = this.config.agentName != null && String(this.config.agentName).trim() !== '' ? String(this.config.agentName).trim() : header.title || 'Chat Assistant';
|
|
29963
|
+
var pillCustomImage = icon.customImage != null && String(icon.customImage).trim() !== '' ? String(icon.customImage).trim() : null;
|
|
29964
|
+
var pillWaveformBars = '<span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span><span class="bar"></span>';
|
|
29965
|
+
var pillIconInner = pillCustomImage ? "<img class=\"ttp-launcher-logo\" src=\"".concat(pillCustomImage, "\" alt=\"\" />") : "<div class=\"ttp-pill-waveform\" aria-hidden=\"true\">".concat(pillWaveformBars, "</div>");
|
|
29966
|
+
var pillIconWrapClass = pillCustomImage ? 'ttp-pill-icon' : 'ttp-pill-icon ttp-pill-icon--wave';
|
|
29967
|
+
return "\n ".concat(styleTag, "\n \n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"text-chat-button-container\">\n ".concat(promptBubbleHTML, "\n ").concat(isPromptEnabled && promptConfig.showPulseRings !== false ? this.generatePulseRingsHTML(promptConfig) : '', "\n <!-- Desktop pill launcher (hidden on mobile) -->\n <button type=\"button\" id=\"text-chat-button\" aria-label=\"Open chat with ").concat(pillTitle, "\">\n <div class=\"").concat(pillIconWrapClass, "\">\n ").concat(pillIconInner, "\n </div>\n <div class=\"ttp-pill-text\">\n <span class=\"ttp-pill-title\">").concat(pillTitle, "</span>\n <span class=\"ttp-pill-status\">\n <span class=\"ttp-launcher-dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n <!-- Mobile FAB (hidden on desktop) -->\n <button class=\"ttp-mobile-fab\" aria-label=\"").concat(this.config.accessibility.ariaLabel, "\">\n <div class=\"ttp-mobile-fab__icon-wrap\">\n <div class=\"ttp-mobile-fab__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-fab__label-wrap\">\n <span class=\"ttp-mobile-fab__label\">").concat(mobileFabLabel, "</span>\n <span class=\"ttp-mobile-fab__status\">\n <span class=\"ttp-mobile-fab__dot\"></span>\n ").concat(header.onlineIndicatorText !== undefined && header.onlineIndicatorText !== null ? header.onlineIndicatorText : t('online'), "\n </span>\n </div>\n </button>\n </div>\n "), "\n\n ").concat(this.config.behavior.hidden ? '' : "\n <div id=\"ttpMobileLanding\" class=\"ttp-mobile-landing\">\n <div class=\"ttp-mobile-landing__header\">\n <div class=\"ttp-mobile-landing__avatar\">\n <div class=\"ttp-mobile-landing__waveform\">\n <span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span>\n </div>\n </div>\n <div class=\"ttp-mobile-landing__info\">\n <div class=\"ttp-mobile-landing__name\">".concat(mobileLandingHeroName, "</div>\n <div class=\"ttp-mobile-landing__status\">\n <span class=\"ttp-mobile-landing__dot\"></span>\n ").concat(this.config.landing.statusText || t('online') + ' • ' + (this.config.landing.subtitle || 'Ready to help'), "\n </div>\n </div>\n <button class=\"ttp-mobile-landing__close\" aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-mobile-landing__error\" id=\"ttpMobileLandingError\" style=\"display:none;\">\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/><line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n <span class=\"ttp-mobile-landing__error-text\"></span>\n </div>\n <div class=\"ttp-mobile-landing__actions\">\n ").concat(showVoice ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--call\" id=\"ttpMobileCallBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n ".concat(this.config.landing.callButtonText || this.config.landing.voiceCardTitle || t('voiceCall'), "\n </button>\n ") : '', "\n ").concat(showText ? "\n <button class=\"ttp-mobile-landing__btn ttp-mobile-landing__btn--text\" id=\"ttpMobileChatBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ".concat(this.config.landing.chatButtonText || this.config.landing.textCardTitle || t('textChat'), "\n </button>\n ") : '', "\n </div>\n ").concat(this.config.footer.show !== false ? "\n <div class=\"ttp-mobile-landing__footer\">\n <div class=\"ttp-mobile-landing__powered\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"10\" height=\"10\">\n <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>\n </svg>\n Powered by <a href=\"https://talktopc.com\" target=\"_blank\" rel=\"noopener\">TalkToPC</a>\n </div>\n </div>\n " : '', "\n </div>\n "), "\n \n <div id=\"text-chat-panel\">\n <div class=\"widget-shell\">\n <div class=\"panel-inner widget-container\" style=\"direction: ").concat(this.config.direction, ";\">\n\n ").concat(showVoice ? this.voiceInterface.generateHTML() : '', "\n ").concat(showText ? this.textInterface.generateHTML() : '', "\n ").concat(this.generateFooterHTML(), "\n </div>\n </div>\n </div>\n ");
|
|
29725
29968
|
}
|
|
29726
29969
|
|
|
29727
29970
|
/**
|
|
@@ -29771,7 +30014,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29771
30014
|
var icon = this.config.icon;
|
|
29772
30015
|
switch (icon.type) {
|
|
29773
30016
|
case 'custom':
|
|
29774
|
-
|
|
30017
|
+
if (icon.customImage != null && String(icon.customImage).trim() !== '') {
|
|
30018
|
+
return "<img src=\"".concat(icon.customImage, "\" alt=\"Chat Assistant\" style=\"width: ").concat(size, "px; height: ").concat(size, "px; object-fit: contain;\" />");
|
|
30019
|
+
}
|
|
30020
|
+
return "<div class=\"ttp-pill-waveform\" aria-hidden=\"true\"><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span><span class=\"bar\"></span></div>";
|
|
29775
30021
|
case 'emoji':
|
|
29776
30022
|
return "<span style=\"font-size: ".concat(size, "px; line-height: 1;\">").concat(icon.emoji, "</span>");
|
|
29777
30023
|
case 'text':
|
|
@@ -29837,7 +30083,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29837
30083
|
|
|
29838
30084
|
// Determine which interfaces to show
|
|
29839
30085
|
var widgetMode = ((_this$config$behavior5 = this.config.behavior) === null || _this$config$behavior5 === void 0 ? void 0 : _this$config$behavior5.mode) || 'unified';
|
|
29840
|
-
var showLanding = widgetMode === 'unified';
|
|
29841
30086
|
var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
|
|
29842
30087
|
var showText = widgetMode === 'unified' || widgetMode === 'text-only';
|
|
29843
30088
|
|
|
@@ -29852,20 +30097,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29852
30097
|
|
|
29853
30098
|
// Detect light vs dark panel background for adaptive footer
|
|
29854
30099
|
var panelBg = panel.backgroundColor || '#16161e';
|
|
29855
|
-
var isLightPanel =
|
|
29856
|
-
if (!panelBg || panelBg.charAt(0) !== '#') return false;
|
|
29857
|
-
var r = parseInt(panelBg.substr(1, 2), 16);
|
|
29858
|
-
var g = parseInt(panelBg.substr(3, 2), 16);
|
|
29859
|
-
var b = parseInt(panelBg.substr(5, 2), 16);
|
|
29860
|
-
return (r * 299 + g * 587 + b * 114) / 1000 > 160;
|
|
29861
|
-
}();
|
|
30100
|
+
var isLightPanel = computeIsLightPanel(panelBg);
|
|
29862
30101
|
var footerTextColor = isLightPanel ? 'rgba(0,0,0,0.4)' : 'rgba(255,255,255,0.35)';
|
|
29863
|
-
var footerLinkColor = isLightPanel
|
|
30102
|
+
var footerLinkColor = talkToPcLinkColorForPanel(isLightPanel, voice, this._rawConfig, showVoice);
|
|
29864
30103
|
var footerBorderColor = isLightPanel ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.06)';
|
|
29865
30104
|
var idleHeroGrad1 = voice.heroGradient1 || '#2a2550';
|
|
29866
30105
|
var idleHeroGrad2 = voice.heroGradient2 || '#1a1a2e';
|
|
30106
|
+
var callSurfaceGradient = "linear-gradient(160deg, ".concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)");
|
|
30107
|
+
/** In-call panel/footer: same gradient as idle so active call matches landing (hero1 → hero2) */
|
|
30108
|
+
var callActivePanelBg = callSurfaceGradient;
|
|
29867
30109
|
var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
|
|
29868
|
-
return "\n /* Inline style display overrides - ensures JS show/hide works with !important CSS */\n #text-chat-panel [style*=\"display: none\"],\n #text-chat-panel [style*=\"display:none\"],\n #text-chat-button-container [style*=\"display: none\"],\n #text-chat-button-container [style*=\"display:none\"],\n #ttpMobileLanding[style*=\"display: none\"],\n #ttpMobileLanding[style*=\"display:none\"] {\n display: none !important;\n }\n #text-chat-panel [style*=\"display: flex\"],\n #text-chat-panel [style*=\"display:flex\"],\n #text-chat-button-container [style*=\"display: flex\"],\n #text-chat-button-container [style*=\"display:flex\"] {\n display: flex !important;\n }\n #text-chat-panel [style*=\"display: block\"],\n #text-chat-panel [style*=\"display:block\"] {\n display: block !important;\n }\n\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n /* Mobile defaults */\n right: 10px").concat(important, ";\n bottom: 10px").concat(important, ";\n left: auto").concat(important, ";\n top: auto").concat(important, ";\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ").concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto').concat(important, ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto').concat(important, ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto').concat(important, ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto').concat(important, ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* \u2500\u2500 Desktop Pill Launcher \u2500\u2500 */\n #text-chat-button {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 7px 16px 7px 7px").concat(important, ";\n z-index: 1").concat(important, ";\n background: ").concat(pillGradient, ";\n border: 1px solid rgba(139,92,246,0.15)").concat(important, ";\n border-radius: 999px").concat(important, ";\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.15)").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: box-shadow 0.25s, transform 0.2s, padding 0.3s, gap 0.3s").concat(important, ";\n font-family: inherit").concat(important, ";\n color: ").concat(pillTextColor, ";\n overflow: hidden").concat(important, ";\n }\n #text-chat-button:hover {\n transform: translateY(-1px)").concat(important, ";\n box-shadow: 0 10px 40px rgba(0,0,0,0.35), 0 4px 12px rgba(0,0,0,0.2)").concat(important, ";\n }\n #text-chat-button.open {\n gap: 0px").concat(important, ";\n padding: 7px").concat(important, ";\n }\n\n .ttp-pill-icon {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: #ffffff").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .ttp-launcher-logo {\n width: 22px").concat(important, "; height: 22px").concat(important, "; border-radius: 50%").concat(important, ";\n object-fit: cover").concat(important, ";\n }\n\n .ttp-pill-text {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 1px").concat(important, ";\n max-width: 120px").concat(important, ";\n opacity: 1").concat(important, ";\n overflow: hidden").concat(important, ";\n white-space: nowrap").concat(important, ";\n transition: max-width 0.3s, opacity 0.2s").concat(important, ";\n }\n #text-chat-button.open .ttp-pill-text {\n max-width: 0").concat(important, ";\n opacity: 0").concat(important, ";\n }\n .ttp-pill-title {\n font-size: 13px").concat(important, "; font-weight: 600").concat(important, "; color: ").concat(pillTextColor, ";\n line-height: 1.2").concat(important, ";\n }\n .ttp-pill-status {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; color: ").concat(pillTextColor, "8c;\n line-height: 1.2").concat(important, ";\n }\n\n /* Online dot (inside pill status) */\n .ttp-launcher-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(pillDotColor, ";\n flex-shrink: 0").concat(important, ";\n animation: ttp-dot-pulse 2s ease-in-out infinite").concat(important, ";\n }\n @keyframes ttp-dot-pulse { 0%,100%{opacity:1} 50%{opacity:.4} }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px").concat(important, ";\n min-height: 56px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 15px").concat(important, ";\n }\n \n #text-chat-panel .header-icon {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n min-width: 40px").concat(important, ";\n min-height: 40px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n .landing-screen {\n padding: 16px").concat(important, ";\n }\n \n .landing-logo {\n font-size: 40px").concat(important, ";\n }\n \n .landing-title {\n font-size: 18px").concat(important, ";\n margin-bottom: 16px").concat(important, ";\n }\n \n .mode-selection {\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .mode-card {\n max-width: 100%").concat(important, ";\n width: 100%").concat(important, ";\n padding: 16px").concat(important, ";\n }\n \n .mode-card-icon {\n width: 50px").concat(important, ";\n height: 50px").concat(important, ";\n font-size: 28px").concat(important, ";\n }\n \n .mode-card-title {\n font-size: 14px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px").concat(important, ";\n min-height: 52px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 14px").concat(important, ";\n }\n \n .landing-logo {\n font-size: 36px").concat(important, ";\n }\n \n .landing-title {\n font-size: 16px").concat(important, ";\n }\n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n transform: translateY(-1px);\n }\n " : '', "\n \n /* Prompt Animation Keyframes */\n @keyframes widget-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(200%); }\n }\n \n @keyframes widget-ripple {\n 0% { transform: scale(1); opacity: 0.6; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n \n @keyframes widget-float {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-8px); }\n }\n \n @keyframes widget-bounce {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-10px); }\n }\n \n @keyframes widget-pulse-ring {\n 0% { transform: scale(1); opacity: 0.4; }\n 100% { transform: scale(1.8); opacity: 0; }\n }\n \n /* Prompt Bubble Container */\n #text-chat-button-container {\n position: fixed").concat(important, ";\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: auto").concat(important, ";\n height: auto").concat(important, ";\n z-index: 10001").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #text-chat-button-container {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-button-container {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* Prompt Bubble Styles */\n .prompt-bubble {\n position: absolute").concat(important, ";\n z-index: 10002").concat(important, ";\n pointer-events: none").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px)").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n /* Ensure animations preserve horizontal centering for top position */\n .prompt-bubble.top.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative").concat(important, ";\n padding: 8px 16px").concat(important, ";\n border-radius: 20px").concat(important, ";\n font-weight: 500").concat(important, ";\n font-size: 14px").concat(important, ";\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3)").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n \n .prompt-bubble-shimmer {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent)").concat(important, ";\n animation: widget-shimmer 2s infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n }\n \n /* Ensure top-positioned bubbles maintain horizontal centering during animations */\n .prompt-bubble.top.animation-bounce,\n .prompt-bubble.top.animation-float,\n .prompt-bubble.top.animation-pulse {\n /* Animation keyframes already include translateX(-50%) for centering */\n }\n \n /* Prompt Bubble Arrow */\n .prompt-bubble-arrow {\n position: absolute").concat(important, ";\n width: 0").concat(important, ";\n height: 0").concat(important, ";\n border: 8px solid transparent").concat(important, ";\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-bottom: none").concat(important, ";\n margin-left: 0").concat(important, ";\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-right: none").concat(important, ";\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-left: none").concat(important, ";\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n \n .prompt-pulse-ring {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: widget-pulse-ring 2s ease-out infinite").concat(important, ";\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s").concat(important, ";\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px").concat(important, ";\n padding: 6px 12px").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px)").concat(important, ";\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none").concat(important, "; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").concat(important, ";\n bottom: calc(54px + 24px)").concat(important, "; /* launcher pill + gap */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: 340px").concat(important, ";\n max-width: calc(100vw - 40px)").concat(important, ";\n height: auto").concat(important, ";\n max-height: calc(100vh - 100px)").concat(important, ";\n background: ").concat(panelBg, ";\n border-radius: 20px").concat(important, ";\n border: ").concat(panel.border || '1px solid rgba(255,255,255,0.08)', ";\n flex-direction: column").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 24px 60px rgba(0,0,0,0.6)").concat(important, ";\n transform-origin: bottom right").concat(important, ";\n opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n opacity: 1").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n /* Shell for panel inner */\n .widget-shell { width: 100%").concat(important, "; padding: 0").concat(important, "; border-radius: 20px").concat(important, "; background: transparent").concat(important, "; overflow: hidden").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; box-sizing: border-box").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n .panel-inner { width: 100%").concat(important, "; background: ").concat(panelBg, "; border-radius: 20px").concat(important, "; border: none").concat(important, "; overflow: hidden").concat(important, "; display:flex").concat(important, "; flex-direction: column").concat(important, "; padding: 0").concat(important, "; box-sizing: border-box").concat(important, "; max-width: 100%").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n\n #text-chat-panel .widget-container {\n width: 100%").concat(important, "; background: ").concat(panelBg, "; overflow: visible").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; border-radius: 20px").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, ";\n }\n\n /* Voice idle: one gradient for voice UI + footer (Powered by), not a flat strip under buttons */\n #text-chat-panel.open:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .landing-screen,\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, "; /* Change from hidden to visible */\n }\n \n /* Header is removed in new design - hero serves as header */\n #text-chat-panel .widget-header { display: none").concat(important, "; }\n\n ").concat(showLanding && this.landingScreen ? this.landingScreen.generateCSS() : '', "\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .ttp-footer {\n padding: 6px 18px 10px").concat(important, ";\n border-top: 1px solid ").concat(footerBorderColor, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n .ttp-footer span { font-size: 10px").concat(important, "; color: ").concat(footerTextColor, "; }\n .ttp-footer a { color: ").concat(footerLinkColor, "; text-decoration: none").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-footer a:hover { opacity: 0.85").concat(important, "; }\n .ttp-footer a b { font-weight: 700").concat(important, "; }\n \n #text-chat-send-hint {\n text-align: center").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n \n .agent-thinking {\n font-style: italic").concat(important, ";\n color: #6B7280").concat(important, ";\n }\n\n /* ========================================\n MOBILE PILL BUTTON & LANDING OVERLAY\n Hidden on desktop, shown on mobile only\n ======================================== */\n .ttp-mobile-fab {\n display: none").concat(important, ";\n }\n\n .ttp-mobile-landing {\n display: none").concat(important, ";\n }\n\n @keyframes ttpWaveAnimation {\n 0%, 100% { transform: scaleY(0.4); }\n 50% { transform: scaleY(1); }\n }\n\n @keyframes ttpPulseAnimation {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @media (max-width: 768px) {\n /* Hide desktop pill button on mobile */\n #text-chat-button {\n display: none !important;\n }\n\n /* Re-flow the container for pill shape */\n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n }\n\n /* Show mobile pill button */\n .ttp-mobile-fab {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 10px 16px 10px 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border: none").concat(important, ";\n border-radius: 24px").concat(important, ";\n cursor: pointer").concat(important, ";\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3)").concat(important, ";\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n z-index: 1").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-fab:hover {\n transform: translateY(-3px)").concat(important, ";\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4)").concat(important, ";\n }\n\n .ttp-mobile-fab__icon-wrap {\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-fab__label-wrap {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 1px").concat(important, ";\n }\n\n .ttp-mobile-fab__label {\n color: ").concat(pillTextColor, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n font-size: 11px").concat(important, ";\n color: ").concat(pillTextColor, "b3;\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(pillDotColor, ";\n border-radius: 50%").concat(important, ";\n box-shadow: 0 0 6px ").concat(pillDotColor, "99;\n }\n\n /* ---- Mobile Landing Overlay ---- */\n .ttp-mobile-landing.active {\n display: block").concat(important, ";\n position: fixed").concat(important, ";\n bottom: 16px").concat(important, ";\n left: 12px").concat(important, ";\n right: 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border-radius: 20px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow:\n 0 10px 40px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1) inset").concat(important, ";\n z-index: 10002").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n }\n\n .ttp-mobile-landing::before {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n height: 1px").concat(important, ";\n background: linear-gradient(90deg,\n transparent 0%,\n rgba(255, 255, 255, 0.3) 50%,\n transparent 100%);\n }\n\n .ttp-mobile-landing__header {\n padding: 14px 16px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .ttp-mobile-landing__avatar {\n width: 44px").concat(important, ";\n height: 44px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 3px").concat(important, ";\n height: 20px").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar {\n width: 3px").concat(important, ";\n background: rgba(255, 255, 255, 0.9)").concat(important, ";\n border-radius: 2px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar:nth-child(1) { height: 6px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(2) { height: 12px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(3) { height: 20px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(4) { height: 10px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(5) { height: 16px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-landing__info {\n flex: 1").concat(important, ";\n min-width: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__name {\n color: #fff").concat(important, ";\n font-size: 15px").concat(important, ";\n font-weight: 600").concat(important, ";\n margin-bottom: 2px").concat(important, ";\n }\n\n .ttp-mobile-landing__status {\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n font-size: 12px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n }\n\n .ttp-mobile-landing__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%").concat(important, ";\n animation: ttpPulseAnimation 2s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__close {\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 10px").concat(important, ";\n background: rgba(255, 255, 255, 0.1)").concat(important, ";\n border: none").concat(important, ";\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__close:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n color: #fff").concat(important, ";\n }\n\n .ttp-mobile-landing__error {\n margin: 0 14px 10px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: #fef2f2").concat(important, ";\n border: 1px solid #fecaca").concat(important, ";\n border-radius: 10px").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 8px").concat(important, ";\n color: #b91c1c").concat(important, ";\n font-size: 13px").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n .ttp-mobile-landing__error svg {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n stroke: #dc2626").concat(important, ";\n }\n\n .ttp-mobile-landing__actions {\n padding: 0 14px 14px").concat(important, ";\n display: flex").concat(important, ";\n gap: 10px").concat(important, ";\n }\n\n .ttp-mobile-landing__btn {\n flex: 1").concat(important, ";\n padding: 14px").concat(important, ";\n border-radius: 12px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: 10px").concat(important, ";\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-landing__btn svg {\n width: 20px").concat(important, ";\n height: 20px").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call {\n background: #fff").concat(important, ";\n color: ").concat(header.backgroundColor || '#7C3AED', ";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call:hover {\n transform: translateY(-2px)").concat(important, ";\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n color: #fff").concat(important, ";\n border: 1px solid rgba(255, 255, 255, 0.1)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n border-color: rgba(255, 255, 255, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__footer {\n padding: 10px 16px").concat(important, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n border-top: 1px solid rgba(255, 255, 255, 0.08)").concat(important, ";\n }\n\n .ttp-mobile-landing__powered {\n color: rgba(255, 255, 255, 0.4)").concat(important, ";\n font-size: 11px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n }\n\n .ttp-mobile-landing__powered svg {\n width: 10px").concat(important, ";\n height: 10px").concat(important, ";\n color: #f59e0b").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a {\n color: rgba(255, 255, 255, 0.6)").concat(important, ";\n text-decoration: none").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a:hover {\n color: #fff").concat(important, ";\n }\n }\n ");
|
|
30110
|
+
var voiceActiveVisibleSelector = '#voiceInterface.active #voiceActiveState:not([style*="display: none"]):not([style*="display:none"])';
|
|
30111
|
+
return "\n /* Inline style display overrides - ensures JS show/hide works with !important CSS */\n #text-chat-panel [style*=\"display: none\"],\n #text-chat-panel [style*=\"display:none\"],\n #text-chat-button-container [style*=\"display: none\"],\n #text-chat-button-container [style*=\"display:none\"],\n #ttpMobileLanding[style*=\"display: none\"],\n #ttpMobileLanding[style*=\"display:none\"] {\n display: none !important;\n }\n #text-chat-panel [style*=\"display: flex\"],\n #text-chat-panel [style*=\"display:flex\"],\n #text-chat-button-container [style*=\"display: flex\"],\n #text-chat-button-container [style*=\"display:flex\"] {\n display: flex !important;\n }\n #text-chat-panel [style*=\"display: block\"],\n #text-chat-panel [style*=\"display:block\"] {\n display: block !important;\n }\n\n /* MOBILE FIRST - Default styles for all devices */\n #text-chat-widget {\n position: fixed !important;\n z-index: 10000".concat(important, ";\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif").concat(important, ";\n /* Mobile defaults */\n right: 10px").concat(important, ";\n bottom: 10px").concat(important, ";\n left: auto").concat(important, ";\n top: auto").concat(important, ";\n }\n \n /* Desktop positioning (only on larger screens) */\n @media (min-width: 769px) {\n #text-chat-widget {\n ").concat(positionStyles, "\n right: ").concat(this.config.position.horizontal === 'right' ? '20px' : 'auto').concat(important, ";\n left: ").concat(this.config.position.horizontal === 'left' ? '20px' : 'auto').concat(important, ";\n bottom: ").concat(this.config.position.vertical === 'bottom' ? '20px' : 'auto').concat(important, ";\n top: ").concat(this.config.position.vertical === 'top' ? '20px' : 'auto').concat(important, ";\n }\n }\n \n /* Mobile override (force mobile positioning) */\n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* \u2500\u2500 Desktop Pill Launcher \u2500\u2500 */\n #text-chat-button {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding-block: 10px").concat(important, ";\n padding-inline-start: 6px").concat(important, ";\n padding-inline-end: 12px").concat(important, ";\n z-index: 1").concat(important, ";\n background: ").concat(pillGradient, ";\n border: 1px solid rgba(139,92,246,0.15)").concat(important, ";\n border-radius: 999px").concat(important, ";\n box-shadow: 0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.15)").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: box-shadow 0.25s, transform 0.2s, padding 0.3s, gap 0.3s").concat(important, ";\n font-family: inherit").concat(important, ";\n color: ").concat(pillTextColor, ";\n overflow: hidden").concat(important, ";\n box-sizing: border-box").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n #text-chat-button:hover {\n transform: translateY(-1px)").concat(important, ";\n box-shadow: 0 10px 40px rgba(0,0,0,0.35), 0 4px 12px rgba(0,0,0,0.2)").concat(important, ";\n }\n #text-chat-button.open {\n gap: 0px").concat(important, ";\n padding: 9px").concat(important, ";\n width: auto").concat(important, ";\n min-width: 0").concat(important, ";\n max-width: none").concat(important, ";\n }\n\n @media (min-width: 769px) {\n #text-chat-button {\n width: 158px").concat(important, ";\n min-width: 158px").concat(important, ";\n max-width: 158px").concat(important, ";\n }\n }\n\n .ttp-pill-icon {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: #ffffff").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .ttp-launcher-logo {\n width: 22px").concat(important, "; height: 22px").concat(important, "; border-radius: 50%").concat(important, ";\n object-fit: cover").concat(important, ";\n }\n\n /* Default pill launcher: same animated waveform as mobile FAB / landing */\n .ttp-pill-icon--wave {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n }\n .ttp-pill-waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n .ttp-pill-waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-pill-waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-pill-waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-pill-text {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, ";\n max-width: 82px").concat(important, ";\n opacity: 1").concat(important, ";\n overflow: hidden").concat(important, ";\n white-space: nowrap").concat(important, ";\n transition: max-width 0.3s, opacity 0.2s").concat(important, ";\n }\n #text-chat-button.open .ttp-pill-text {\n max-width: 0").concat(important, ";\n opacity: 0").concat(important, ";\n }\n .ttp-pill-title {\n font-size: 13px").concat(important, "; font-weight: 600").concat(important, "; color: ").concat(pillTextColor, ";\n line-height: 1.25").concat(important, ";\n overflow: hidden").concat(important, ";\n text-overflow: ellipsis").concat(important, ";\n }\n .ttp-pill-status {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 4px").concat(important, ";\n font-size: 11px").concat(important, "; color: ").concat(pillTextColor, "8c;\n line-height: 1.25").concat(important, ";\n }\n\n /* Online dot (inside pill status) */\n .ttp-launcher-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(pillDotColor, ";\n flex-shrink: 0").concat(important, ";\n animation: ttp-dot-pulse 2s ease-in-out infinite").concat(important, ";\n }\n @keyframes ttp-dot-pulse { 0%,100%{opacity:1} 50%{opacity:.4} }\n \n @media (max-width: 768px) {\n #text-chat-widget {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n transform: none !important;\n }\n \n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n }\n \n #text-chat-panel {\n position: fixed !important;\n left: 10px !important;\n right: 10px !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: 60px !important; /* Add top spacing */\n width: auto !important;\n max-width: none !important;\n height: auto !important; /* Change from max-height to auto */\n max-height: none !important; /* Remove max-height */\n transform: none !important;\n margin: 0 !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 10px 14px").concat(important, ";\n min-height: 56px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 15px").concat(important, ";\n }\n \n #text-chat-panel .header-icon {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n min-width: 40px").concat(important, ";\n min-height: 40px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 12px 16px !important;\n min-height: 48px !important;\n }\n \n #text-chat-send {\n min-width: 48px !important;\n min-height: 48px !important;\n width: 48px !important;\n height: 48px !important;\n }\n \n }\n \n @media (max-width: 480px) {\n #text-chat-widget {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n \n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n }\n \n #text-chat-panel {\n left: 8px !important;\n right: 8px !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: 50px !important; /* Add top spacing for very small screens */\n height: auto !important;\n max-height: none !important;\n }\n \n #text-chat-panel .widget-header {\n padding: 8px 12px").concat(important, ";\n min-height: 52px").concat(important, ";\n }\n \n #text-chat-panel .header-title {\n font-size: 14px").concat(important, ";\n }\n \n }\n \n ").concat(anim.enableHover ? "\n #text-chat-button:hover {\n transform: translateY(-1px);\n }\n " : '', "\n \n /* Prompt Animation Keyframes */\n @keyframes widget-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(200%); }\n }\n \n @keyframes widget-ripple {\n 0% { transform: scale(1); opacity: 0.6; }\n 100% { transform: scale(2.5); opacity: 0; }\n }\n \n @keyframes widget-float {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-8px); }\n }\n \n @keyframes widget-bounce {\n 0%, 100% { transform: translateX(-50%) translateY(0); }\n 50% { transform: translateX(-50%) translateY(-10px); }\n }\n \n @keyframes widget-pulse-ring {\n 0% { transform: scale(1); opacity: 0.4; }\n 100% { transform: scale(1.8); opacity: 0; }\n }\n \n /* Prompt Bubble Container */\n #text-chat-button-container {\n position: fixed").concat(important, ";\n ").concat(this.config.position.vertical === 'bottom' ? "bottom: ".concat(((_this$config$position = this.config.position.offset) === null || _this$config$position === void 0 ? void 0 : _this$config$position.y) || 20, "px;") : "top: ".concat(((_this$config$position2 = this.config.position.offset) === null || _this$config$position2 === void 0 ? void 0 : _this$config$position2.y) || 20, "px;"), "\n ").concat(this.config.position.horizontal === 'right' ? "right: ".concat(((_this$config$position3 = this.config.position.offset) === null || _this$config$position3 === void 0 ? void 0 : _this$config$position3.x) || 20, "px;") : "left: ".concat(((_this$config$position4 = this.config.position.offset) === null || _this$config$position4 === void 0 ? void 0 : _this$config$position4.x) || 20, "px;"), "\n width: auto").concat(important, ";\n height: auto").concat(important, ";\n z-index: 10001").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #text-chat-button-container {\n right: 10px !important;\n bottom: 10px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n @media (max-width: 480px) {\n #text-chat-button-container {\n right: 8px !important;\n bottom: 8px !important;\n left: auto !important;\n top: auto !important;\n }\n }\n \n /* Prompt Bubble Styles */\n .prompt-bubble {\n position: absolute").concat(important, ";\n z-index: 10002").concat(important, ";\n pointer-events: none").concat(important, ";\n white-space: nowrap").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 18px)").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n }\n \n .prompt-bubble.left {\n right: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n .prompt-bubble.right {\n left: calc(100% + 12px)").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n }\n \n /* Ensure animations preserve horizontal centering for top position */\n .prompt-bubble.top.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble.top.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n transform: translateX(-50%)").concat(important, "; /* Keep centering */\n }\n \n .prompt-bubble-content {\n position: relative").concat(important, ";\n padding: 8px 16px").concat(important, ";\n border-radius: 20px").concat(important, ";\n font-weight: 500").concat(important, ";\n font-size: 14px").concat(important, ";\n box-shadow: 0 4px 15px rgba(124, 58, 237, 0.3)").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n \n .prompt-bubble-shimmer {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent)").concat(important, ";\n animation: widget-shimmer 2s infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-bounce {\n animation: widget-bounce 1s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-pulse {\n animation: pulse 2s ease-in-out infinite").concat(important, ";\n }\n \n .prompt-bubble.animation-float {\n animation: widget-float 2s ease-in-out infinite").concat(important, ";\n }\n \n /* Ensure top-positioned bubbles maintain horizontal centering during animations */\n .prompt-bubble.top.animation-bounce,\n .prompt-bubble.top.animation-float,\n .prompt-bubble.top.animation-pulse {\n /* Animation keyframes already include translateX(-50%) for centering */\n }\n \n /* Prompt Bubble Arrow */\n .prompt-bubble-arrow {\n position: absolute").concat(important, ";\n width: 0").concat(important, ";\n height: 0").concat(important, ";\n border: 8px solid transparent").concat(important, ";\n }\n \n .prompt-bubble.top .prompt-bubble-arrow {\n top: 100%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translateX(-50%)").concat(important, ";\n border-top-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-bottom: none").concat(important, ";\n margin-left: 0").concat(important, ";\n }\n \n .prompt-bubble.left .prompt-bubble-arrow {\n left: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-left-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-right: none").concat(important, ";\n }\n \n .prompt-bubble.right .prompt-bubble-arrow {\n right: 100%").concat(important, ";\n top: 50%").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n border-right-color: var(--prompt-bubble-bg-color, #7c3aed)").concat(important, ";\n border-left: none").concat(important, ";\n }\n \n /* Pulse Rings */\n .prompt-pulse-rings {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n pointer-events: none").concat(important, ";\n }\n \n .prompt-pulse-ring {\n position: absolute").concat(important, ";\n inset: 0").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: widget-pulse-ring 2s ease-out infinite").concat(important, ";\n }\n \n .prompt-pulse-ring:nth-child(2) {\n animation-delay: 0.5s").concat(important, ";\n }\n \n /* Mobile adjustments for prompt bubble */\n @media (max-width: 768px) {\n .prompt-bubble-content {\n font-size: 12px").concat(important, ";\n padding: 6px 12px").concat(important, ";\n }\n \n .prompt-bubble.top {\n bottom: calc(100% + 14px)").concat(important, ";\n }\n \n .prompt-bubble.left,\n .prompt-bubble.right {\n display: none").concat(important, "; /* Hide side prompts on mobile */\n }\n }\n \n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").concat(important, ";\n bottom: calc(54px + 24px)").concat(important, "; /* launcher pill + gap */\n ").concat(this.config.position.horizontal === 'right' ? 'right: 20px;' : 'left: 20px;', "\n width: 340px").concat(important, ";\n max-width: calc(100vw - 40px)").concat(important, ";\n height: auto").concat(important, ";\n max-height: calc(100vh - 100px)").concat(important, ";\n background: ").concat(panelBg, ";\n border-radius: 20px").concat(important, ";\n border: ").concat(panel.border || '1px solid rgba(255,255,255,0.08)', ";\n flex-direction: column").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 24px 60px rgba(0,0,0,0.6)").concat(important, ";\n transform-origin: bottom right").concat(important, ";\n opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n #text-chat-panel.open {\n display: flex").concat(important, ";\n opacity: 1").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n /* Shell for panel inner */\n .widget-shell { width: 100%").concat(important, "; padding: 0").concat(important, "; border-radius: 20px").concat(important, "; background: transparent").concat(important, "; overflow: hidden").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; box-sizing: border-box").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n .panel-inner { width: 100%").concat(important, "; background: ").concat(panelBg, "; border-radius: 20px").concat(important, "; border: none").concat(important, "; overflow: hidden").concat(important, "; display:flex").concat(important, "; flex-direction: column").concat(important, "; padding: 0").concat(important, "; box-sizing: border-box").concat(important, "; max-width: 100%").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, "; }\n\n #text-chat-panel .widget-container {\n width: 100%").concat(important, "; background: ").concat(panelBg, "; overflow: visible").concat(important, "; display: flex").concat(important, "; flex-direction: column").concat(important, "; border-radius: 20px").concat(important, "; flex: 1").concat(important, "; min-height: 0").concat(important, ";\n }\n\n /* Voice idle: one gradient for voice UI + footer (Powered by), not a flat strip under buttons */\n #text-chat-panel.open:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceIdleVisibleSelector, ") {\n background: linear-gradient(160deg, ").concat(idleHeroGrad1, " 0%, ").concat(idleHeroGrad2, " 100%)").concat(important, ";\n }\n\n /* Voice active call: same hero gradient as idle + mobile minimized bar */\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel .widget-container:has(").concat(voiceActiveVisibleSelector, ") {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .widget-shell {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .panel-inner {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n #text-chat-panel.open:has(").concat(voiceActiveVisibleSelector, ") .ttp-footer {\n background: ").concat(callActivePanelBg).concat(important, ";\n }\n \n /* Ensure content areas can scroll when height is constrained */\n #text-chat-panel .widget-container > .voice-interface,\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, "; /* Change from hidden to visible */\n }\n \n /* Header is removed in new design - hero serves as header */\n #text-chat-panel .widget-header { display: none").concat(important, "; }\n\n ").concat(showVoice ? this.voiceInterface.generateCSS() : '', "\n ").concat(showText ? this.textInterface.generateCSS() : '', "\n \n /* Footer Branding */\n .ttp-footer {\n padding: 6px 18px 10px").concat(important, ";\n border-top: 1px solid ").concat(footerBorderColor, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n .ttp-footer span { font-size: 10px").concat(important, "; color: ").concat(footerTextColor, "; }\n .ttp-footer a { color: ").concat(footerLinkColor, "; text-decoration: none").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-footer a:hover { opacity: 0.85").concat(important, "; }\n .ttp-footer a b { font-weight: 700").concat(important, "; }\n \n #text-chat-send-hint {\n text-align: center").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n \n .agent-thinking {\n font-style: italic").concat(important, ";\n color: #6B7280").concat(important, ";\n }\n\n /* ========================================\n MOBILE PILL BUTTON & LANDING OVERLAY\n Hidden on desktop, shown on mobile only\n ======================================== */\n .ttp-mobile-fab {\n display: none").concat(important, ";\n }\n\n .ttp-mobile-landing {\n display: none").concat(important, ";\n }\n\n @keyframes ttpWaveAnimation {\n 0%, 100% { transform: scaleY(0.4); }\n 50% { transform: scaleY(1); }\n }\n\n @keyframes ttpPulseAnimation {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n @media (max-width: 768px) {\n /* Hide desktop pill button on mobile */\n #text-chat-button {\n display: none !important;\n }\n\n /* Re-flow the container for pill shape */\n #text-chat-button-container {\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n }\n\n /* Show mobile pill button */\n .ttp-mobile-fab {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 10px 16px 10px 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border: none").concat(important, ";\n border-radius: 24px").concat(important, ";\n cursor: pointer").concat(important, ";\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3)").concat(important, ";\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n z-index: 1").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-fab:hover {\n transform: translateY(-3px)").concat(important, ";\n box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4)").concat(important, ";\n }\n\n .ttp-mobile-fab__icon-wrap {\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 2px").concat(important, ";\n height: 16px").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar {\n width: 2px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 1px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-fab__waveform .bar:nth-child(1) { height: 5px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(2) { height: 10px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(3) { height: 16px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(4) { height: 8px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-fab__waveform .bar:nth-child(5) { height: 12px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-fab__label-wrap {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 1px").concat(important, ";\n }\n\n .ttp-mobile-fab__label {\n color: ").concat(pillTextColor, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n font-size: 11px").concat(important, ";\n color: ").concat(pillTextColor, "b3;\n line-height: 1.2").concat(important, ";\n }\n\n .ttp-mobile-fab__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(pillDotColor, ";\n border-radius: 50%").concat(important, ";\n box-shadow: 0 0 6px ").concat(pillDotColor, "99;\n }\n\n /* ---- Mobile Landing Overlay ---- */\n .ttp-mobile-landing.active {\n display: block").concat(important, ";\n position: fixed").concat(important, ";\n bottom: 16px").concat(important, ";\n left: 12px").concat(important, ";\n right: 12px").concat(important, ";\n background: ").concat(pillGradient, ";\n border-radius: 20px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow:\n 0 10px 40px rgba(0, 0, 0, 0.3),\n 0 0 0 1px rgba(255, 255, 255, 0.1) inset").concat(important, ";\n z-index: 10002").concat(important, ";\n font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif").concat(important, ";\n }\n\n .ttp-mobile-landing::before {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n height: 1px").concat(important, ";\n background: linear-gradient(90deg,\n transparent 0%,\n rgba(255, 255, 255, 0.3) 50%,\n transparent 100%);\n }\n\n .ttp-mobile-landing__header {\n padding: 14px 16px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .ttp-mobile-landing__avatar {\n width: 44px").concat(important, ";\n height: 44px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 3px").concat(important, ";\n height: 20px").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar {\n width: 3px").concat(important, ";\n background: rgba(255, 255, 255, 0.9)").concat(important, ";\n border-radius: 2px").concat(important, ";\n animation: ttpWaveAnimation 0.8s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__waveform .bar:nth-child(1) { height: 6px").concat(important, "; animation-delay: 0s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(2) { height: 12px").concat(important, "; animation-delay: 0.1s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(3) { height: 20px").concat(important, "; animation-delay: 0.2s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(4) { height: 10px").concat(important, "; animation-delay: 0.3s").concat(important, "; }\n .ttp-mobile-landing__waveform .bar:nth-child(5) { height: 16px").concat(important, "; animation-delay: 0.4s").concat(important, "; }\n\n .ttp-mobile-landing__info {\n flex: 1").concat(important, ";\n min-width: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__name {\n color: #fff").concat(important, ";\n font-size: 15px").concat(important, ";\n font-weight: 600").concat(important, ";\n margin-bottom: 2px").concat(important, ";\n }\n\n .ttp-mobile-landing__status {\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n font-size: 12px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n }\n\n .ttp-mobile-landing__dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n background: ").concat(header.onlineIndicatorDotColor || '#10b981', ";\n border-radius: 50%").concat(important, ";\n animation: ttpPulseAnimation 2s ease-in-out infinite").concat(important, ";\n }\n\n .ttp-mobile-landing__close {\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 10px").concat(important, ";\n background: rgba(255, 255, 255, 0.1)").concat(important, ";\n border: none").concat(important, ";\n color: rgba(255, 255, 255, 0.7)").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__close:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n color: #fff").concat(important, ";\n }\n\n .ttp-mobile-landing__error {\n margin: 0 14px 10px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: #fef2f2").concat(important, ";\n border: 1px solid #fecaca").concat(important, ";\n border-radius: 10px").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 8px").concat(important, ";\n color: #b91c1c").concat(important, ";\n font-size: 13px").concat(important, ";\n line-height: 1.4").concat(important, ";\n }\n .ttp-mobile-landing__error svg {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n stroke: #dc2626").concat(important, ";\n }\n\n .ttp-mobile-landing__actions {\n padding: 0 14px 14px").concat(important, ";\n display: flex").concat(important, ";\n gap: 10px").concat(important, ";\n }\n\n .ttp-mobile-landing__btn {\n flex: 1").concat(important, ";\n padding: 14px").concat(important, ";\n border-radius: 12px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n gap: 10px").concat(important, ";\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1)").concat(important, ";\n touch-action: manipulation").concat(important, ";\n -webkit-tap-highlight-color: transparent").concat(important, ";\n }\n\n .ttp-mobile-landing__btn svg {\n width: 20px").concat(important, ";\n height: 20px").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call {\n background: #fff").concat(important, ";\n color: ").concat(header.backgroundColor || '#7C3AED', ";\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--call:hover {\n transform: translateY(-2px)").concat(important, ";\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text {\n background: rgba(255, 255, 255, 0.15)").concat(important, ";\n color: #fff").concat(important, ";\n border: 1px solid rgba(255, 255, 255, 0.1)").concat(important, ";\n }\n\n .ttp-mobile-landing__btn--text:hover {\n background: rgba(255, 255, 255, 0.2)").concat(important, ";\n border-color: rgba(255, 255, 255, 0.2)").concat(important, ";\n }\n\n .ttp-mobile-landing__footer {\n padding: 10px 16px").concat(important, ";\n display: flex").concat(important, ";\n justify-content: center").concat(important, ";\n border-top: 1px solid rgba(255, 255, 255, 0.08)").concat(important, ";\n }\n\n .ttp-mobile-landing__powered {\n color: rgba(255, 255, 255, 0.4)").concat(important, ";\n font-size: 11px").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n }\n\n .ttp-mobile-landing__powered svg {\n width: 10px").concat(important, ";\n height: 10px").concat(important, ";\n color: #f59e0b").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a {\n color: ").concat(footerLinkColor).concat(important, ";\n text-decoration: none").concat(important, ";\n }\n\n .ttp-mobile-landing__powered a:hover {\n opacity: 0.88").concat(important, ";\n }\n }\n ");
|
|
29869
30112
|
}
|
|
29870
30113
|
}, {
|
|
29871
30114
|
key: "setupWidgetEvents",
|
|
@@ -29916,6 +30159,16 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29916
30159
|
return _this7.showText();
|
|
29917
30160
|
};
|
|
29918
30161
|
}
|
|
30162
|
+
var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
|
|
30163
|
+
if (textUnifiedBackBtn) {
|
|
30164
|
+
textUnifiedBackBtn.onclick = function () {
|
|
30165
|
+
var _this7$config$behavio;
|
|
30166
|
+
var widgetMode = ((_this7$config$behavio = _this7.config.behavior) === null || _this7$config$behavio === void 0 ? void 0 : _this7$config$behavio.mode) || 'unified';
|
|
30167
|
+
if (widgetMode !== 'unified') return;
|
|
30168
|
+
_this7.showLanding();
|
|
30169
|
+
_this7._openMobileCallTextLanding();
|
|
30170
|
+
};
|
|
30171
|
+
}
|
|
29919
30172
|
|
|
29920
30173
|
// Build wave bars inside the orb (desktop active call)
|
|
29921
30174
|
var waveQueryRoot = this.config.useShadowDOM ? this.shadowRoot : document.getElementById('ttp-widget-container');
|
|
@@ -29932,280 +30185,67 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
29932
30185
|
|
|
29933
30186
|
// Voice selection events (based on widget mode)
|
|
29934
30187
|
var widgetMode = ((_this$config$behavior6 = this.config.behavior) === null || _this$config$behavior6 === void 0 ? void 0 : _this$config$behavior6.mode) || 'unified';
|
|
29935
|
-
var
|
|
30188
|
+
var isUnified = widgetMode === 'unified';
|
|
29936
30189
|
var showVoice = widgetMode === 'unified' || widgetMode === 'voice-only';
|
|
29937
30190
|
var showText = widgetMode === 'unified' || widgetMode === 'text-only';
|
|
29938
30191
|
var backBtn = this.shadowRoot.getElementById('backBtn');
|
|
29939
|
-
var landing = this.shadowRoot.getElementById('landingScreen');
|
|
29940
30192
|
var textInterface = this.shadowRoot.getElementById('textInterface');
|
|
29941
30193
|
var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
|
|
30194
|
+
var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
|
|
29942
30195
|
|
|
29943
30196
|
// Setup back button handler
|
|
29944
30197
|
if (backBtn) {
|
|
29945
30198
|
backBtn.onclick = function () {
|
|
29946
30199
|
var _this7$voiceInterface, _this7$voiceInterface3;
|
|
29947
|
-
// Check if we're showing a domain error
|
|
30200
|
+
// Check if we're showing a domain error — clear it and return to voice hero
|
|
29948
30201
|
if ((_this7$voiceInterface = _this7.voiceInterface) !== null && _this7$voiceInterface !== void 0 && _this7$voiceInterface.isShowingDomainError) {
|
|
29949
30202
|
var _this7$voiceInterface2;
|
|
29950
|
-
console.log('🔙 Back button clicked - clearing domain error and returning to
|
|
30203
|
+
console.log('🔙 Back button clicked - clearing domain error and returning to voice hero');
|
|
29951
30204
|
// Clear the domain error flag
|
|
29952
30205
|
_this7.voiceInterface.isShowingDomainError = false;
|
|
29953
30206
|
// Reset the connecting state (this will restore normal UI)
|
|
29954
30207
|
if ((_this7$voiceInterface2 = _this7.voiceInterface) !== null && _this7$voiceInterface2 !== void 0 && _this7$voiceInterface2.resetConnectingState) {
|
|
29955
30208
|
_this7.voiceInterface.resetConnectingState();
|
|
29956
30209
|
}
|
|
29957
|
-
// Now show landing (will work since error flag is cleared)
|
|
29958
30210
|
_this7.showLanding();
|
|
30211
|
+
_this7._openMobileCallTextLanding();
|
|
29959
30212
|
return;
|
|
29960
30213
|
}
|
|
29961
30214
|
if ((_this7$voiceInterface3 = _this7.voiceInterface) !== null && _this7$voiceInterface3 !== void 0 && _this7$voiceInterface3.isActive) {
|
|
29962
30215
|
// If call is active, show message inside widget instead of modal
|
|
29963
30216
|
_this7.showBackButtonWarning();
|
|
29964
30217
|
} else if (window.innerWidth <= 768) {
|
|
29965
|
-
// On mobile, close panel and return to FAB
|
|
29966
|
-
var panel = _this7.shadowRoot.getElementById('text-chat-panel');
|
|
29967
|
-
if (panel) {
|
|
29968
|
-
panel.classList.remove('open');
|
|
29969
|
-
_this7.isOpen = false;
|
|
29970
|
-
}
|
|
29971
|
-
var fab = _this7.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
29972
|
-
if (fab) fab.style.display = '';
|
|
29973
30218
|
_this7.showLanding();
|
|
30219
|
+
_this7._openMobileCallTextLanding();
|
|
29974
30220
|
} else {
|
|
29975
|
-
// Desktop:
|
|
30221
|
+
// Desktop: return to voice hero (unified home)
|
|
29976
30222
|
_this7.showLanding();
|
|
29977
30223
|
}
|
|
29978
30224
|
};
|
|
29979
30225
|
}
|
|
29980
|
-
if (
|
|
29981
|
-
this.landingScreen.setupEventHandlers({
|
|
29982
|
-
onSelectVoice: function () {
|
|
29983
|
-
var _onSelectVoice = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
29984
|
-
var _this7$voiceInterface4, _this7$voiceInterface0, _this7$shadowRoot, _this7$voiceInterface5, _this7$shadowRoot2, _this7$shadowRoot3, _this7$voiceInterface6, panel, idleState, floatingButton, mobileFab, _this7$voiceInterface7, _this7$voiceInterface8, _this7$voiceInterface9, _this7$voiceInterface1, _this7$config$behavio, _widgetMode, _this7$voiceInterface11, _this7$voiceInterface12, _this7$config$behavio2, _this7$voiceInterface10, _this7$voiceInterface13, _this7$shadowRoot4, _this7$shadowRoot5, existingBar, _floatingButton, _mobileFab, _widgetMode2, _t;
|
|
29985
|
-
return _regenerator().w(function (_context2) {
|
|
29986
|
-
while (1) switch (_context2.p = _context2.n) {
|
|
29987
|
-
case 0:
|
|
29988
|
-
if (!_this7.isStartingCall) {
|
|
29989
|
-
_context2.n = 1;
|
|
29990
|
-
break;
|
|
29991
|
-
}
|
|
29992
|
-
console.log('⚠️ Call already starting, ignoring duplicate click');
|
|
29993
|
-
return _context2.a(2);
|
|
29994
|
-
case 1:
|
|
29995
|
-
// Call the callback if provided
|
|
29996
|
-
if (typeof _this7.config.onVoiceCallButtonClick === 'function') {
|
|
29997
|
-
try {
|
|
29998
|
-
_this7.config.onVoiceCallButtonClick({
|
|
29999
|
-
timestamp: Date.now(),
|
|
30000
|
-
widgetState: 'start'
|
|
30001
|
-
});
|
|
30002
|
-
} catch (error) {
|
|
30003
|
-
console.error('Error in onVoiceCallButtonClick callback:', error);
|
|
30004
|
-
}
|
|
30005
|
-
}
|
|
30006
|
-
_this7.isStartingCall = true;
|
|
30007
|
-
_context2.p = 2;
|
|
30008
|
-
// Show voice interface first (needed for UI state)
|
|
30009
|
-
// Note: If showVoice() throws, finally block will still reset flag
|
|
30010
|
-
_this7.showVoice();
|
|
30011
|
-
|
|
30012
|
-
// CRITICAL: On mobile, hide widget panel IMMEDIATELY to prevent showing old UI
|
|
30013
|
-
// The idle state with "Connecting..." should never be visible on mobile
|
|
30014
|
-
if (!((_this7$voiceInterface4 = _this7.voiceInterface) !== null && _this7$voiceInterface4 !== void 0 && _this7$voiceInterface4.isMobile)) {
|
|
30015
|
-
_context2.n = 4;
|
|
30016
|
-
break;
|
|
30017
|
-
}
|
|
30018
|
-
// Hide widget panel immediately before showing any connecting state
|
|
30019
|
-
panel = ((_this7$shadowRoot = _this7.shadowRoot) === null || _this7$shadowRoot === void 0 ? void 0 : _this7$shadowRoot.getElementById('text-chat-panel')) || document.getElementById('text-chat-panel');
|
|
30020
|
-
if (panel) {
|
|
30021
|
-
panel.classList.remove('open');
|
|
30022
|
-
panel.style.display = 'none';
|
|
30023
|
-
}
|
|
30024
|
-
// Hide idle state to prevent it from showing
|
|
30025
|
-
idleState = (_this7$voiceInterface5 = _this7.voiceInterface) === null || _this7$voiceInterface5 === void 0 || (_this7$voiceInterface5 = _this7$voiceInterface5.shadowRoot) === null || _this7$voiceInterface5 === void 0 ? void 0 : _this7$voiceInterface5.getElementById('voiceIdleState');
|
|
30026
|
-
if (idleState) {
|
|
30027
|
-
idleState.style.display = 'none';
|
|
30028
|
-
}
|
|
30029
|
-
// Hide floating button immediately so minimized bar is visible
|
|
30030
|
-
floatingButton = ((_this7$shadowRoot2 = _this7.shadowRoot) === null || _this7$shadowRoot2 === void 0 ? void 0 : _this7$shadowRoot2.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
|
|
30031
|
-
if (floatingButton) {
|
|
30032
|
-
floatingButton.style.display = 'none';
|
|
30033
|
-
}
|
|
30034
|
-
mobileFab = (_this7$shadowRoot3 = _this7.shadowRoot) === null || _this7$shadowRoot3 === void 0 ? void 0 : _this7$shadowRoot3.querySelector('.ttp-mobile-fab');
|
|
30035
|
-
if (mobileFab) {
|
|
30036
|
-
mobileFab.style.display = 'none';
|
|
30037
|
-
}
|
|
30038
|
-
// Create minimized bar with connecting state
|
|
30039
|
-
if (!((_this7$voiceInterface6 = _this7.voiceInterface) !== null && _this7$voiceInterface6 !== void 0 && _this7$voiceInterface6.createMobileMinimizedBar)) {
|
|
30040
|
-
_context2.n = 3;
|
|
30041
|
-
break;
|
|
30042
|
-
}
|
|
30043
|
-
_this7.voiceInterface.createMobileMinimizedBar();
|
|
30044
|
-
// Show connecting status in minimized bar
|
|
30045
|
-
_this7.voiceInterface.updateMobileStatus('connecting');
|
|
30046
|
-
// Start timer and waveform immediately - timer runs inside mobile bar (owns its DOM)
|
|
30047
|
-
(_this7$voiceInterface7 = (_this7$voiceInterface8 = _this7.voiceInterface).startWaveformAnimation) === null || _this7$voiceInterface7 === void 0 || _this7$voiceInterface7.call(_this7$voiceInterface8);
|
|
30048
|
-
// Ensure UI is painted before starting heavy operations
|
|
30049
|
-
_context2.n = 3;
|
|
30050
|
-
return new Promise(function (resolve) {
|
|
30051
|
-
return requestAnimationFrame(function () {
|
|
30052
|
-
return requestAnimationFrame(resolve);
|
|
30053
|
-
});
|
|
30054
|
-
});
|
|
30055
|
-
case 3:
|
|
30056
|
-
_context2.n = 5;
|
|
30057
|
-
break;
|
|
30058
|
-
case 4:
|
|
30059
|
-
// Desktop: Show connecting/loading state in idle state
|
|
30060
|
-
// This provides feedback during WebSocket connection and SDK initialization
|
|
30061
|
-
if ((_this7$voiceInterface9 = _this7.voiceInterface) !== null && _this7$voiceInterface9 !== void 0 && _this7$voiceInterface9.showConnectingState) {
|
|
30062
|
-
_this7.voiceInterface.showConnectingState();
|
|
30063
|
-
}
|
|
30064
|
-
case 5:
|
|
30065
|
-
_context2.n = 6;
|
|
30066
|
-
return _this7.startVoiceCall();
|
|
30067
|
-
case 6:
|
|
30068
|
-
if (!((_this7$voiceInterface0 = _this7.voiceInterface) !== null && _this7$voiceInterface0 !== void 0 && _this7$voiceInterface0.isActive)) {
|
|
30069
|
-
_context2.n = 7;
|
|
30070
|
-
break;
|
|
30071
|
-
}
|
|
30072
|
-
console.log('✅ Voice call started successfully');
|
|
30073
|
-
_context2.n = 9;
|
|
30074
|
-
break;
|
|
30075
|
-
case 7:
|
|
30076
|
-
// This shouldn't happen if startVoiceCall() throws properly, but just in case
|
|
30077
|
-
console.warn('⚠️ startVoiceCall() returned but call is not active');
|
|
30078
|
-
|
|
30079
|
-
// CRITICAL: Check if we're showing a domain error - if so, stay on voice interface
|
|
30080
|
-
if (!_this7._isDomainErrorVisible()) {
|
|
30081
|
-
_context2.n = 8;
|
|
30082
|
-
break;
|
|
30083
|
-
}
|
|
30084
|
-
// Set currentView to voice so we don't return to landing
|
|
30085
|
-
_this7.currentView = 'voice';
|
|
30086
|
-
// Ensure voice interface is visible
|
|
30087
|
-
_this7.showVoice();
|
|
30088
|
-
// Don't reset connecting state or return to landing - stay on voice interface showing error
|
|
30089
|
-
console.log('✅ Staying on voice interface with domain error displayed');
|
|
30090
|
-
return _context2.a(2);
|
|
30091
|
-
case 8:
|
|
30092
|
-
// Not a domain error - reset connecting state and return to landing
|
|
30093
|
-
console.log('⚠️ Not a domain error - returning to landing screen');
|
|
30094
|
-
if ((_this7$voiceInterface1 = _this7.voiceInterface) !== null && _this7$voiceInterface1 !== void 0 && _this7$voiceInterface1.resetConnectingState) {
|
|
30095
|
-
_this7.voiceInterface.resetConnectingState();
|
|
30096
|
-
}
|
|
30097
|
-
_widgetMode = ((_this7$config$behavio = _this7.config.behavior) === null || _this7$config$behavio === void 0 ? void 0 : _this7$config$behavio.mode) || 'unified';
|
|
30098
|
-
if (_widgetMode === 'unified') {
|
|
30099
|
-
_this7.showLanding();
|
|
30100
|
-
}
|
|
30101
|
-
case 9:
|
|
30102
|
-
_context2.n = 12;
|
|
30103
|
-
break;
|
|
30104
|
-
case 10:
|
|
30105
|
-
_context2.p = 10;
|
|
30106
|
-
_t = _context2.v;
|
|
30107
|
-
if (!(_t.isServerRejection || _t.name === 'ServerRejected')) {
|
|
30108
|
-
_context2.n = 11;
|
|
30109
|
-
break;
|
|
30110
|
-
}
|
|
30111
|
-
// Server rejection is expected - the error handler will show domain error message
|
|
30112
|
-
// Reset connecting state but don't log as error
|
|
30113
|
-
if ((_this7$voiceInterface10 = _this7.voiceInterface) !== null && _this7$voiceInterface10 !== void 0 && _this7$voiceInterface10.resetConnectingState) {
|
|
30114
|
-
_this7.voiceInterface.resetConnectingState();
|
|
30115
|
-
}
|
|
30116
|
-
// Don't show toast for server rejection - domain error handler will show message
|
|
30117
|
-
return _context2.a(2);
|
|
30118
|
-
case 11:
|
|
30119
|
-
// Log other errors (permission denied, etc.)
|
|
30120
|
-
console.error('❌ Failed to start voice call:', _t);
|
|
30121
|
-
|
|
30122
|
-
// Reset connecting state on error
|
|
30123
|
-
if ((_this7$voiceInterface11 = _this7.voiceInterface) !== null && _this7$voiceInterface11 !== void 0 && _this7$voiceInterface11.resetConnectingState) {
|
|
30124
|
-
_this7.voiceInterface.resetConnectingState();
|
|
30125
|
-
}
|
|
30126
|
-
|
|
30127
|
-
// Clean up mobile bar if it was created early
|
|
30128
|
-
if ((_this7$voiceInterface12 = _this7.voiceInterface) !== null && _this7$voiceInterface12 !== void 0 && _this7$voiceInterface12.isMobile) {
|
|
30129
|
-
existingBar = document.getElementById('mobile-voice-call-bar-container');
|
|
30130
|
-
if (existingBar && (_this7$voiceInterface13 = _this7.voiceInterface) !== null && _this7$voiceInterface13 !== void 0 && _this7$voiceInterface13.removeMobileMinimizedBar) {
|
|
30131
|
-
_this7.voiceInterface.removeMobileMinimizedBar();
|
|
30132
|
-
}
|
|
30133
|
-
// Restore floating button if it was hidden
|
|
30134
|
-
_floatingButton = ((_this7$shadowRoot4 = _this7.shadowRoot) === null || _this7$shadowRoot4 === void 0 ? void 0 : _this7$shadowRoot4.getElementById('text-chat-button')) || document.getElementById('text-chat-button');
|
|
30135
|
-
if (_floatingButton) {
|
|
30136
|
-
_floatingButton.style.display = '';
|
|
30137
|
-
}
|
|
30138
|
-
_mobileFab = (_this7$shadowRoot5 = _this7.shadowRoot) === null || _this7$shadowRoot5 === void 0 ? void 0 : _this7$shadowRoot5.querySelector('.ttp-mobile-fab');
|
|
30139
|
-
if (_mobileFab) {
|
|
30140
|
-
_mobileFab.style.display = '';
|
|
30141
|
-
}
|
|
30142
|
-
}
|
|
30143
|
-
|
|
30144
|
-
// Show user-friendly error message (unless it's a user cancellation)
|
|
30145
|
-
if (_t.message !== 'Call cancelled by user') {
|
|
30146
|
-
_this7.showErrorToast(_t.message || 'Failed to start voice call. Please try again.', 'error');
|
|
30147
|
-
}
|
|
30148
|
-
|
|
30149
|
-
// Return to landing screen on error
|
|
30150
|
-
_widgetMode2 = ((_this7$config$behavio2 = _this7.config.behavior) === null || _this7$config$behavio2 === void 0 ? void 0 : _this7$config$behavio2.mode) || 'unified';
|
|
30151
|
-
if (_widgetMode2 === 'unified') {
|
|
30152
|
-
_this7.showLanding();
|
|
30153
|
-
}
|
|
30154
|
-
case 12:
|
|
30155
|
-
_context2.p = 12;
|
|
30156
|
-
// ✅ Always reset flag, even if showVoice() or startVoiceCall() throws
|
|
30157
|
-
_this7.isStartingCall = false;
|
|
30158
|
-
return _context2.f(12);
|
|
30159
|
-
case 13:
|
|
30160
|
-
return _context2.a(2);
|
|
30161
|
-
}
|
|
30162
|
-
}, _callee2, null, [[2, 10, 12, 13]]);
|
|
30163
|
-
}));
|
|
30164
|
-
function onSelectVoice() {
|
|
30165
|
-
return _onSelectVoice.apply(this, arguments);
|
|
30166
|
-
}
|
|
30167
|
-
return onSelectVoice;
|
|
30168
|
-
}(),
|
|
30169
|
-
onSelectText: function onSelectText() {
|
|
30170
|
-
return _this7.showText();
|
|
30171
|
-
}
|
|
30172
|
-
});
|
|
30173
|
-
|
|
30174
|
-
// Restore previous view state if user had selected an interface, otherwise show landing
|
|
30226
|
+
if (isUnified) {
|
|
30175
30227
|
if (this.currentView === 'text') {
|
|
30176
|
-
// User was on text interface, restore it
|
|
30177
|
-
if (landing) landing.classList.remove('active');
|
|
30178
30228
|
if (textInterface) textInterface.classList.add('active');
|
|
30179
30229
|
if (voiceInterface) voiceInterface.classList.remove('active');
|
|
30180
|
-
if (backBtn
|
|
30230
|
+
if (backBtn) backBtn.classList.add('visible');
|
|
30181
30231
|
if (newChatBtn) newChatBtn.style.display = '';
|
|
30182
|
-
} else
|
|
30183
|
-
//
|
|
30184
|
-
|
|
30232
|
+
} else {
|
|
30233
|
+
// Text-only path is text branch; everything else is unified home (voice hero)
|
|
30234
|
+
this.currentView = 'voice';
|
|
30185
30235
|
if (textInterface) textInterface.classList.remove('active');
|
|
30186
30236
|
if (voiceInterface) voiceInterface.classList.add('active');
|
|
30187
|
-
if (backBtn
|
|
30237
|
+
if (backBtn) backBtn.classList.remove('visible');
|
|
30188
30238
|
if (newChatBtn) newChatBtn.style.display = 'none';
|
|
30189
|
-
} else {
|
|
30190
|
-
// Initial state or landing: show landing screen
|
|
30191
|
-
this.currentView = 'landing';
|
|
30192
|
-
if (landing) landing.classList.add('active');
|
|
30193
|
-
if (textInterface) textInterface.classList.remove('active');
|
|
30194
|
-
if (voiceInterface) voiceInterface.classList.remove('active');
|
|
30195
|
-
// Hide back button on landing screen (only exists in unified mode)
|
|
30196
|
-
if (backBtn && widgetMode === 'unified') backBtn.classList.remove('visible');
|
|
30197
30239
|
}
|
|
30198
30240
|
} else if (widgetMode === 'voice-only') {
|
|
30199
30241
|
// Voice-only mode: show voice interface directly
|
|
30200
30242
|
if (voiceInterface) voiceInterface.classList.add('active');
|
|
30201
30243
|
if (textInterface) textInterface.classList.remove('active');
|
|
30202
|
-
if (landing) landing.classList.remove('active');
|
|
30203
30244
|
// Back button doesn't exist in voice-only mode (only in unified)
|
|
30204
30245
|
} else if (widgetMode === 'text-only') {
|
|
30205
30246
|
// Text-only mode: show text interface directly
|
|
30206
30247
|
if (textInterface) textInterface.classList.add('active');
|
|
30207
30248
|
if (voiceInterface) voiceInterface.classList.remove('active');
|
|
30208
|
-
if (landing) landing.classList.remove('active');
|
|
30209
30249
|
// Back button doesn't exist in text-only mode (only in unified)
|
|
30210
30250
|
}
|
|
30211
30251
|
|
|
@@ -30220,13 +30260,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30220
30260
|
}
|
|
30221
30261
|
|
|
30222
30262
|
// Setup header button handlers
|
|
30223
|
-
var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
|
|
30224
30263
|
if (newChatBtn) {
|
|
30225
30264
|
newChatBtn.onclick = function () {
|
|
30226
30265
|
return _this7.textInterface.startNewChat();
|
|
30227
30266
|
};
|
|
30228
|
-
// Hide new chat
|
|
30229
|
-
if (
|
|
30267
|
+
// Hide new chat on unified home (voice hero) initially
|
|
30268
|
+
if (isUnified && this.currentView !== 'text') {
|
|
30230
30269
|
newChatBtn.style.display = 'none';
|
|
30231
30270
|
}
|
|
30232
30271
|
}
|
|
@@ -30244,28 +30283,25 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30244
30283
|
value: function startNewChat() {
|
|
30245
30284
|
this.textInterface.startNewChat();
|
|
30246
30285
|
}
|
|
30286
|
+
|
|
30287
|
+
/**
|
|
30288
|
+
* Unified-mode "home": voice idle hero. Name kept for VoiceInterface callbacks.
|
|
30289
|
+
* Legacy two-card in-panel mode picker has been removed.
|
|
30290
|
+
*/
|
|
30247
30291
|
}, {
|
|
30248
30292
|
key: "showLanding",
|
|
30249
30293
|
value: function showLanding() {
|
|
30250
30294
|
if (!this.shadowRoot) return;
|
|
30251
|
-
|
|
30252
|
-
// On desktop, skip landing — show voice idle state as default entry
|
|
30253
|
-
if (window.innerWidth > 768) {
|
|
30254
|
-
this.showVoice();
|
|
30255
|
-
return;
|
|
30256
|
-
}
|
|
30257
30295
|
if (this._isDomainErrorVisible()) return;
|
|
30258
30296
|
var widgetMode = this.config.behavior.mode || 'unified';
|
|
30259
30297
|
if (widgetMode !== 'unified') return;
|
|
30260
|
-
this.currentView = 'landing';
|
|
30261
|
-
var landing = this.shadowRoot.getElementById('landingScreen');
|
|
30262
30298
|
var textInterface = this.shadowRoot.getElementById('textInterface');
|
|
30263
30299
|
var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
|
|
30264
30300
|
var backBtn = this.shadowRoot.getElementById('backBtn');
|
|
30265
30301
|
var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
|
|
30266
|
-
|
|
30302
|
+
this.currentView = 'voice';
|
|
30267
30303
|
if (textInterface) textInterface.classList.remove('active');
|
|
30268
|
-
if (voiceInterface) voiceInterface.classList.
|
|
30304
|
+
if (voiceInterface) voiceInterface.classList.add('active');
|
|
30269
30305
|
if (backBtn) backBtn.classList.remove('visible');
|
|
30270
30306
|
if (newChatBtn) newChatBtn.style.display = 'none';
|
|
30271
30307
|
}
|
|
@@ -30274,11 +30310,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30274
30310
|
value: function showText() {
|
|
30275
30311
|
if (!this.shadowRoot) return;
|
|
30276
30312
|
this.currentView = 'text'; // Track state
|
|
30277
|
-
var landing = this.shadowRoot.getElementById('landingScreen');
|
|
30278
30313
|
var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
|
|
30279
30314
|
var backBtn = this.shadowRoot.getElementById('backBtn');
|
|
30280
30315
|
var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
|
|
30281
|
-
if (landing) landing.classList.remove('active');
|
|
30282
30316
|
if (voiceInterface) voiceInterface.classList.remove('active');
|
|
30283
30317
|
this.textInterface.show();
|
|
30284
30318
|
// Show back button when not on landing (only in unified mode)
|
|
@@ -30300,45 +30334,73 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30300
30334
|
value: function showVoice() {
|
|
30301
30335
|
if (!this.shadowRoot) return;
|
|
30302
30336
|
this.currentView = 'voice'; // Track state
|
|
30303
|
-
var landing = this.shadowRoot.getElementById('landingScreen');
|
|
30304
30337
|
var textInterface = this.shadowRoot.getElementById('textInterface');
|
|
30305
30338
|
var voiceInterface = this.shadowRoot.getElementById('voiceInterface');
|
|
30306
30339
|
var backBtn = this.shadowRoot.getElementById('backBtn');
|
|
30307
30340
|
var newChatBtn = this.shadowRoot.getElementById('newChatBtn');
|
|
30308
|
-
if (landing) landing.classList.remove('active');
|
|
30309
30341
|
if (textInterface) textInterface.classList.remove('active');
|
|
30310
30342
|
if (voiceInterface) voiceInterface.classList.add('active');
|
|
30311
|
-
//
|
|
30343
|
+
// Voice hero is unified home — no header back (text chat uses its own back bar)
|
|
30312
30344
|
var widgetMode = this.config.behavior.mode || 'unified';
|
|
30313
|
-
if (backBtn && widgetMode === 'unified') backBtn.classList.
|
|
30345
|
+
if (backBtn && widgetMode === 'unified') backBtn.classList.remove('visible');
|
|
30314
30346
|
// Hide new chat button on voice interface (not applicable)
|
|
30315
30347
|
if (newChatBtn) newChatBtn.style.display = 'none';
|
|
30316
30348
|
}
|
|
30349
|
+
|
|
30350
|
+
/**
|
|
30351
|
+
* Mobile (≤768px): close chat panel and show Call vs Chat overlay (#ttpMobileLanding).
|
|
30352
|
+
* Hides FAB while landing is open. No-op on desktop or if mobile chrome is missing.
|
|
30353
|
+
*/
|
|
30317
30354
|
}, {
|
|
30318
|
-
key: "
|
|
30319
|
-
value: function
|
|
30355
|
+
key: "_openMobileCallTextLanding",
|
|
30356
|
+
value: function _openMobileCallTextLanding() {
|
|
30320
30357
|
var _this8 = this;
|
|
30321
|
-
if (!this.shadowRoot) return;
|
|
30358
|
+
if (!this.shadowRoot || window.innerWidth > 768) return;
|
|
30322
30359
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
30323
30360
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
30324
30361
|
if (!mobileFab || !mobileLanding) return;
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
|
|
30329
|
-
|
|
30330
|
-
var
|
|
30362
|
+
|
|
30363
|
+
// Defer showing landing until after the current pointer/click event finishes.
|
|
30364
|
+
// Otherwise document's "outside click" listener runs in the same bubble as e.g. the text
|
|
30365
|
+
// "Back" button: composedPath includes the panel but not #ttpMobileLanding, so it treated
|
|
30366
|
+
// the click as "outside" and closed the landing immediately (user only saw the FAB again).
|
|
30367
|
+
var open = function open() {
|
|
30368
|
+
if (!_this8.shadowRoot || window.innerWidth > 768) return;
|
|
30369
|
+
var panel = _this8.shadowRoot.getElementById('text-chat-panel');
|
|
30370
|
+
if (panel) {
|
|
30371
|
+
panel.classList.remove('open');
|
|
30372
|
+
_this8.isOpen = false;
|
|
30373
|
+
}
|
|
30331
30374
|
if (_this8.config.promptAnimation.hideAfterClick) {
|
|
30332
30375
|
_this8.hidePrompt();
|
|
30333
30376
|
}
|
|
30334
|
-
// Clear any previous error banner
|
|
30335
30377
|
var errorBanner = _this8.shadowRoot.getElementById('ttpMobileLandingError');
|
|
30336
30378
|
if (errorBanner) errorBanner.style.display = 'none';
|
|
30337
|
-
|
|
30338
|
-
|
|
30379
|
+
var fab = _this8.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
30380
|
+
var landing = _this8.shadowRoot.getElementById('ttpMobileLanding');
|
|
30381
|
+
if (!fab || !landing) return;
|
|
30382
|
+
fab.style.display = 'none';
|
|
30383
|
+
landing.classList.add('active');
|
|
30339
30384
|
_this8.isMobileLandingOpen = true;
|
|
30340
30385
|
};
|
|
30341
|
-
|
|
30386
|
+
queueMicrotask(open);
|
|
30387
|
+
}
|
|
30388
|
+
}, {
|
|
30389
|
+
key: "setupMobileWidgetEvents",
|
|
30390
|
+
value: function setupMobileWidgetEvents() {
|
|
30391
|
+
var _this9 = this;
|
|
30392
|
+
if (!this.shadowRoot) return;
|
|
30393
|
+
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
30394
|
+
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
30395
|
+
if (!mobileFab || !mobileLanding) return;
|
|
30396
|
+
var closeMobileLanding = function closeMobileLanding() {
|
|
30397
|
+
mobileLanding.classList.remove('active');
|
|
30398
|
+
mobileFab.style.display = '';
|
|
30399
|
+
_this9.isMobileLandingOpen = false;
|
|
30400
|
+
};
|
|
30401
|
+
mobileFab.onclick = function () {
|
|
30402
|
+
return _this9._openMobileCallTextLanding();
|
|
30403
|
+
};
|
|
30342
30404
|
var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
|
|
30343
30405
|
if (mobileClose) {
|
|
30344
30406
|
mobileClose.onclick = closeMobileLanding;
|
|
@@ -30347,31 +30409,39 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30347
30409
|
if (mobileCallBtn) {
|
|
30348
30410
|
mobileCallBtn.onclick = function () {
|
|
30349
30411
|
closeMobileLanding();
|
|
30350
|
-
var
|
|
30351
|
-
if (
|
|
30352
|
-
|
|
30353
|
-
|
|
30354
|
-
_this8.showVoice();
|
|
30412
|
+
var panel = _this9.shadowRoot.getElementById('text-chat-panel');
|
|
30413
|
+
if (panel) {
|
|
30414
|
+
panel.classList.add('open');
|
|
30415
|
+
_this9.isOpen = true;
|
|
30355
30416
|
}
|
|
30417
|
+
mobileFab.style.display = 'none';
|
|
30418
|
+
_this9.showVoice();
|
|
30419
|
+
// Landing already chose "Voice call" — start the call (mic permission / pre-prompt) instead of
|
|
30420
|
+
// leaving users on a second "Start Call" tap that feels broken.
|
|
30421
|
+
queueMicrotask(function () {
|
|
30422
|
+
_this9.startVoiceCall().catch(function (err) {
|
|
30423
|
+
console.error('[TTPChatWidget] Mobile landing voice start failed:', err);
|
|
30424
|
+
});
|
|
30425
|
+
});
|
|
30356
30426
|
};
|
|
30357
30427
|
}
|
|
30358
30428
|
var mobileChatBtn = this.shadowRoot.getElementById('ttpMobileChatBtn');
|
|
30359
30429
|
if (mobileChatBtn) {
|
|
30360
30430
|
mobileChatBtn.onclick = function () {
|
|
30361
30431
|
closeMobileLanding();
|
|
30362
|
-
var panel =
|
|
30432
|
+
var panel = _this9.shadowRoot.getElementById('text-chat-panel');
|
|
30363
30433
|
if (panel) {
|
|
30364
30434
|
panel.classList.add('open');
|
|
30365
|
-
|
|
30435
|
+
_this9.isOpen = true;
|
|
30366
30436
|
}
|
|
30367
30437
|
mobileFab.style.display = 'none';
|
|
30368
|
-
|
|
30438
|
+
_this9.showText();
|
|
30369
30439
|
};
|
|
30370
30440
|
}
|
|
30371
30441
|
|
|
30372
30442
|
// Close mobile landing on outside click
|
|
30373
30443
|
document.addEventListener('click', function (e) {
|
|
30374
|
-
if (!
|
|
30444
|
+
if (!_this9.isMobileLandingOpen) return;
|
|
30375
30445
|
var path = e.composedPath();
|
|
30376
30446
|
if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
|
|
30377
30447
|
closeMobileLanding();
|
|
@@ -30380,7 +30450,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30380
30450
|
|
|
30381
30451
|
// Close mobile landing on Escape
|
|
30382
30452
|
document.addEventListener('keydown', function (e) {
|
|
30383
|
-
if (e.key === 'Escape' &&
|
|
30453
|
+
if (e.key === 'Escape' && _this9.isMobileLandingOpen) {
|
|
30384
30454
|
closeMobileLanding();
|
|
30385
30455
|
}
|
|
30386
30456
|
});
|
|
@@ -30388,10 +30458,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30388
30458
|
}, {
|
|
30389
30459
|
key: "setupKeyboardNavigation",
|
|
30390
30460
|
value: function setupKeyboardNavigation() {
|
|
30391
|
-
var
|
|
30461
|
+
var _this0 = this;
|
|
30392
30462
|
document.addEventListener('keydown', function (e) {
|
|
30393
|
-
if (e.key === 'Escape' &&
|
|
30394
|
-
|
|
30463
|
+
if (e.key === 'Escape' && _this0.isOpen) {
|
|
30464
|
+
_this0.togglePanel();
|
|
30395
30465
|
}
|
|
30396
30466
|
});
|
|
30397
30467
|
}
|
|
@@ -30402,7 +30472,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30402
30472
|
}, {
|
|
30403
30473
|
key: "setupPromptAnimation",
|
|
30404
30474
|
value: function setupPromptAnimation() {
|
|
30405
|
-
var
|
|
30475
|
+
var _this1 = this;
|
|
30406
30476
|
if (!this.shadowRoot) return;
|
|
30407
30477
|
var promptConfig = this.config.promptAnimation || {};
|
|
30408
30478
|
// Default to disabled if not specified (enabled === true means explicitly enabled)
|
|
@@ -30432,7 +30502,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30432
30502
|
// Auto-hide after configured seconds (only if widget is closed)
|
|
30433
30503
|
if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
|
|
30434
30504
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
30435
|
-
|
|
30505
|
+
_this1.hidePrompt();
|
|
30436
30506
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
30437
30507
|
}
|
|
30438
30508
|
|
|
@@ -30444,7 +30514,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30444
30514
|
// Wrap the callback to also hide pulse rings
|
|
30445
30515
|
this.config.onConversationStart = function () {
|
|
30446
30516
|
// Hide pulse rings when call starts
|
|
30447
|
-
var pulseRings =
|
|
30517
|
+
var pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
|
|
30448
30518
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
30449
30519
|
|
|
30450
30520
|
// Call original callback if it exists
|
|
@@ -30456,7 +30526,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30456
30526
|
// Also listen to recordingStarted event from SDK if available
|
|
30457
30527
|
if (this.voiceInterface.sdk.voiceSDK) {
|
|
30458
30528
|
this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
|
|
30459
|
-
var pulseRings =
|
|
30529
|
+
var pulseRings = _this1.shadowRoot.getElementById('prompt-pulse-rings');
|
|
30460
30530
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
30461
30531
|
});
|
|
30462
30532
|
}
|
|
@@ -30504,7 +30574,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30504
30574
|
}, {
|
|
30505
30575
|
key: "showPrompt",
|
|
30506
30576
|
value: function showPrompt() {
|
|
30507
|
-
var
|
|
30577
|
+
var _this10 = this;
|
|
30508
30578
|
if (!this.shadowRoot) return;
|
|
30509
30579
|
var promptConfig = this.config.promptAnimation || {};
|
|
30510
30580
|
// Default to enabled if not specified
|
|
@@ -30524,8 +30594,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30524
30594
|
// Function to actually show the elements
|
|
30525
30595
|
var doShow = function doShow() {
|
|
30526
30596
|
// Show prompt bubble (check both shadow root and document for compatibility)
|
|
30527
|
-
var promptBubble =
|
|
30528
|
-
if (!promptBubble &&
|
|
30597
|
+
var promptBubble = _this10.shadowRoot.getElementById('prompt-bubble');
|
|
30598
|
+
if (!promptBubble && _this10.shadowRoot !== document) {
|
|
30529
30599
|
promptBubble = document.getElementById('prompt-bubble');
|
|
30530
30600
|
}
|
|
30531
30601
|
if (promptBubble) {
|
|
@@ -30539,8 +30609,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30539
30609
|
|
|
30540
30610
|
// Show pulse rings if enabled
|
|
30541
30611
|
if (promptConfig.showPulseRings !== false) {
|
|
30542
|
-
var _pulseRings =
|
|
30543
|
-
if (!_pulseRings &&
|
|
30612
|
+
var _pulseRings = _this10.shadowRoot.getElementById('prompt-pulse-rings');
|
|
30613
|
+
if (!_pulseRings && _this10.shadowRoot !== document) {
|
|
30544
30614
|
_pulseRings = document.getElementById('prompt-pulse-rings');
|
|
30545
30615
|
}
|
|
30546
30616
|
if (_pulseRings) {
|
|
@@ -30577,7 +30647,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30577
30647
|
}
|
|
30578
30648
|
// Start new timer
|
|
30579
30649
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
30580
|
-
|
|
30650
|
+
_this10.hidePrompt();
|
|
30581
30651
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
30582
30652
|
}
|
|
30583
30653
|
}
|
|
@@ -30593,7 +30663,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30593
30663
|
}, {
|
|
30594
30664
|
key: "_doTogglePanel",
|
|
30595
30665
|
value: function _doTogglePanel() {
|
|
30596
|
-
var
|
|
30666
|
+
var _this11 = this;
|
|
30597
30667
|
if (!this.shadowRoot) return;
|
|
30598
30668
|
this.isOpen = !this.isOpen;
|
|
30599
30669
|
var panel = this.shadowRoot.getElementById('text-chat-panel');
|
|
@@ -30612,7 +30682,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30612
30682
|
// Panel is opening - hide prompt
|
|
30613
30683
|
this.hidePrompt();
|
|
30614
30684
|
setTimeout(function () {
|
|
30615
|
-
var input =
|
|
30685
|
+
var input = _this11.shadowRoot.getElementById('messageInput');
|
|
30616
30686
|
if (input) input.focus();
|
|
30617
30687
|
}, 100);
|
|
30618
30688
|
} else {
|
|
@@ -30624,13 +30694,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30624
30694
|
// Panel is closing - show prompt (if enabled)
|
|
30625
30695
|
this.showPrompt();
|
|
30626
30696
|
setTimeout(function () {
|
|
30627
|
-
var
|
|
30628
|
-
var promptBubble =
|
|
30697
|
+
var _this11$config$prompt;
|
|
30698
|
+
var promptBubble = _this11.shadowRoot.getElementById('prompt-bubble');
|
|
30629
30699
|
if (promptBubble && promptBubble.style.display === 'none') {
|
|
30630
30700
|
promptBubble.style.display = 'block';
|
|
30631
30701
|
}
|
|
30632
|
-
var pulseRings =
|
|
30633
|
-
if (pulseRings && ((
|
|
30702
|
+
var pulseRings = _this11.shadowRoot.getElementById('prompt-pulse-rings');
|
|
30703
|
+
if (pulseRings && ((_this11$config$prompt = _this11.config.promptAnimation) === null || _this11$config$prompt === void 0 ? void 0 : _this11$config$prompt.showPulseRings) !== false) {
|
|
30634
30704
|
if (pulseRings.style.display === 'none') {
|
|
30635
30705
|
pulseRings.style.display = 'block';
|
|
30636
30706
|
}
|
|
@@ -30774,17 +30844,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30774
30844
|
}, {
|
|
30775
30845
|
key: "startChat",
|
|
30776
30846
|
value: function () {
|
|
30777
|
-
var _startChat = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
30778
|
-
return _regenerator().w(function (
|
|
30779
|
-
while (1) switch (
|
|
30847
|
+
var _startChat = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
30848
|
+
return _regenerator().w(function (_context2) {
|
|
30849
|
+
while (1) switch (_context2.n) {
|
|
30780
30850
|
case 0:
|
|
30781
30851
|
// No-op with single-shot design; connection happens per message
|
|
30782
30852
|
this.isActive = true;
|
|
30783
30853
|
this.textInterface.setActive(true);
|
|
30784
30854
|
case 1:
|
|
30785
|
-
return
|
|
30855
|
+
return _context2.a(2);
|
|
30786
30856
|
}
|
|
30787
|
-
},
|
|
30857
|
+
}, _callee2, this);
|
|
30788
30858
|
}));
|
|
30789
30859
|
function startChat() {
|
|
30790
30860
|
return _startChat.apply(this, arguments);
|
|
@@ -30794,16 +30864,16 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30794
30864
|
}, {
|
|
30795
30865
|
key: "sendMessage",
|
|
30796
30866
|
value: function () {
|
|
30797
|
-
var _sendMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
30798
|
-
return _regenerator().w(function (
|
|
30799
|
-
while (1) switch (
|
|
30867
|
+
var _sendMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
30868
|
+
return _regenerator().w(function (_context3) {
|
|
30869
|
+
while (1) switch (_context3.n) {
|
|
30800
30870
|
case 0:
|
|
30801
|
-
|
|
30871
|
+
_context3.n = 1;
|
|
30802
30872
|
return this.textInterface.sendMessage();
|
|
30803
30873
|
case 1:
|
|
30804
|
-
return
|
|
30874
|
+
return _context3.a(2);
|
|
30805
30875
|
}
|
|
30806
|
-
},
|
|
30876
|
+
}, _callee3, this);
|
|
30807
30877
|
}));
|
|
30808
30878
|
function sendMessage() {
|
|
30809
30879
|
return _sendMessage.apply(this, arguments);
|
|
@@ -30899,7 +30969,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30899
30969
|
}, {
|
|
30900
30970
|
key: "updateConfig",
|
|
30901
30971
|
value: function updateConfig(newConfig) {
|
|
30902
|
-
var _this$
|
|
30972
|
+
var _this$config2, _this$config3, _this$config$voice8, _this$config$voice9, _this$config$voice0, _this$config$voice1, _this$config$voice10;
|
|
30903
30973
|
// Deep merge nested objects
|
|
30904
30974
|
var mergedConfig = _objectSpread({}, this.config);
|
|
30905
30975
|
|
|
@@ -30908,14 +30978,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30908
30978
|
mergedConfig.panel = _objectSpread(_objectSpread({}, this.config.panel), newConfig.panel);
|
|
30909
30979
|
}
|
|
30910
30980
|
|
|
30911
|
-
// Deep merge voice config if it exists
|
|
30981
|
+
// Deep merge voice config if it exists (root `agentName` only — ignore `voice.agentName`)
|
|
30912
30982
|
if (newConfig.voice) {
|
|
30913
|
-
|
|
30983
|
+
var _newConfig$voice = newConfig.voice,
|
|
30984
|
+
_ignoredVoiceAgentName = _newConfig$voice.agentName,
|
|
30985
|
+
voicePatch = _objectWithoutProperties(_newConfig$voice, _excluded);
|
|
30986
|
+
mergedConfig.voice = _objectSpread(_objectSpread({}, this.config.voice), voicePatch);
|
|
30914
30987
|
// Deep merge micButtonHint if it exists
|
|
30915
30988
|
if (newConfig.voice.micButtonHint) {
|
|
30916
30989
|
var _this$config$voice7;
|
|
30917
30990
|
mergedConfig.voice.micButtonHint = _objectSpread(_objectSpread({}, (_this$config$voice7 = this.config.voice) === null || _this$config$voice7 === void 0 ? void 0 : _this$config$voice7.micButtonHint), newConfig.voice.micButtonHint);
|
|
30918
30991
|
}
|
|
30992
|
+
delete mergedConfig.voice.agentName;
|
|
30919
30993
|
}
|
|
30920
30994
|
|
|
30921
30995
|
// Deep merge text config if it exists
|
|
@@ -30935,8 +31009,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
30935
31009
|
|
|
30936
31010
|
// Update direction if language changed to RTL language
|
|
30937
31011
|
if (newConfig.language !== undefined) {
|
|
30938
|
-
var
|
|
30939
|
-
if (
|
|
31012
|
+
var langBase = String(newConfig.language).toLowerCase().split(/[-_]/)[0];
|
|
31013
|
+
if (langBase === 'he' || langBase === 'ar') {
|
|
30940
31014
|
mergedConfig.direction = 'rtl';
|
|
30941
31015
|
} else if (newConfig.direction === undefined) {
|
|
30942
31016
|
mergedConfig.direction = 'ltr';
|
|
@@ -31013,9 +31087,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31013
31087
|
});
|
|
31014
31088
|
|
|
31015
31089
|
// Store current language before merge to detect changes
|
|
31016
|
-
var oldLanguage = ((_this$
|
|
31090
|
+
var oldLanguage = ((_this$config2 = this.config) === null || _this$config2 === void 0 ? void 0 : _this$config2.language) || 'en';
|
|
31017
31091
|
// Store current useShadowDOM setting
|
|
31018
|
-
var oldUseShadowDOM = ((_this$
|
|
31092
|
+
var oldUseShadowDOM = ((_this$config3 = this.config) === null || _this$config3 === void 0 ? void 0 : _this$config3.useShadowDOM) !== false;
|
|
31019
31093
|
this.config = this.mergeWithDefaults(mergedConfig);
|
|
31020
31094
|
|
|
31021
31095
|
// Check if useShadowDOM changed - if so, need to recreate container
|
|
@@ -31094,6 +31168,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31094
31168
|
// Ensure language is correctly passed - use the merged config value
|
|
31095
31169
|
var currentLanguage = this.config.language || 'en';
|
|
31096
31170
|
var voiceConfig = _objectSpread(_objectSpread(_objectSpread({}, this.config), this.config.voice), {}, {
|
|
31171
|
+
agentName: this.config.agentName,
|
|
31097
31172
|
language: currentLanguage,
|
|
31098
31173
|
// Use the current language from merged config
|
|
31099
31174
|
translations: this.translations,
|
|
@@ -31126,18 +31201,6 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31126
31201
|
});
|
|
31127
31202
|
this.textInterface = new _TextInterface_js__WEBPACK_IMPORTED_MODULE_2__.TextInterface(textConfig, this.sdk);
|
|
31128
31203
|
|
|
31129
|
-
// Recreate landing screen if in unified mode
|
|
31130
|
-
var widgetMode = ((_this$config$behavior7 = this.config.behavior) === null || _this$config$behavior7 === void 0 ? void 0 : _this$config$behavior7.mode) || 'unified';
|
|
31131
|
-
if (widgetMode === 'unified') {
|
|
31132
|
-
var landingConfig = _objectSpread(_objectSpread({}, this.config), {}, {
|
|
31133
|
-
translations: this.translations,
|
|
31134
|
-
shadowRoot: this.shadowRoot
|
|
31135
|
-
});
|
|
31136
|
-
this.landingScreen = new _LandingScreen_js__WEBPACK_IMPORTED_MODULE_3__.LandingScreen(landingConfig);
|
|
31137
|
-
} else {
|
|
31138
|
-
this.landingScreen = null;
|
|
31139
|
-
}
|
|
31140
|
-
|
|
31141
31204
|
// Recreate widget with new config (after interfaces are created)
|
|
31142
31205
|
this.createWidget();
|
|
31143
31206
|
|
|
@@ -31188,19 +31251,19 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31188
31251
|
}, {
|
|
31189
31252
|
key: "startVoiceCall",
|
|
31190
31253
|
value: function () {
|
|
31191
|
-
var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
31192
|
-
return _regenerator().w(function (
|
|
31193
|
-
while (1) switch (
|
|
31254
|
+
var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
31255
|
+
return _regenerator().w(function (_context4) {
|
|
31256
|
+
while (1) switch (_context4.n) {
|
|
31194
31257
|
case 0:
|
|
31195
|
-
|
|
31258
|
+
_context4.n = 1;
|
|
31196
31259
|
return this.voiceInterface.startVoiceCall();
|
|
31197
31260
|
case 1:
|
|
31198
31261
|
// Flush pending tools after SDK connects
|
|
31199
31262
|
this._flushPendingClientTools();
|
|
31200
31263
|
case 2:
|
|
31201
|
-
return
|
|
31264
|
+
return _context4.a(2);
|
|
31202
31265
|
}
|
|
31203
|
-
},
|
|
31266
|
+
}, _callee4, this);
|
|
31204
31267
|
}));
|
|
31205
31268
|
function startVoiceCall() {
|
|
31206
31269
|
return _startVoiceCall.apply(this, arguments);
|
|
@@ -31253,26 +31316,26 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31253
31316
|
}, {
|
|
31254
31317
|
key: "injectData",
|
|
31255
31318
|
value: (function () {
|
|
31256
|
-
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
31319
|
+
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(data) {
|
|
31257
31320
|
var _this$voiceInterface5;
|
|
31258
31321
|
var options,
|
|
31259
31322
|
voiceSDK,
|
|
31260
31323
|
ack,
|
|
31261
|
-
|
|
31262
|
-
|
|
31263
|
-
return _regenerator().w(function (
|
|
31264
|
-
while (1) switch (
|
|
31324
|
+
_args5 = arguments,
|
|
31325
|
+
_t;
|
|
31326
|
+
return _regenerator().w(function (_context5) {
|
|
31327
|
+
while (1) switch (_context5.p = _context5.n) {
|
|
31265
31328
|
case 0:
|
|
31266
|
-
options =
|
|
31329
|
+
options = _args5.length > 1 && _args5[1] !== undefined ? _args5[1] : {};
|
|
31267
31330
|
if (!(!data || !data.trim())) {
|
|
31268
|
-
|
|
31331
|
+
_context5.n = 1;
|
|
31269
31332
|
break;
|
|
31270
31333
|
}
|
|
31271
31334
|
console.warn('TTPChatWidget: Cannot inject empty data');
|
|
31272
31335
|
throw new Error('Cannot inject empty data');
|
|
31273
31336
|
case 1:
|
|
31274
31337
|
if (!(!this.voiceInterface || !this.voiceInterface.isActive)) {
|
|
31275
|
-
|
|
31338
|
+
_context5.n = 2;
|
|
31276
31339
|
break;
|
|
31277
31340
|
}
|
|
31278
31341
|
console.warn('TTPChatWidget: Cannot inject data - voice call is not active');
|
|
@@ -31281,28 +31344,28 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31281
31344
|
// Check if SDK is available
|
|
31282
31345
|
voiceSDK = (_this$voiceInterface5 = this.voiceInterface) === null || _this$voiceInterface5 === void 0 ? void 0 : _this$voiceInterface5.getVoiceSDK();
|
|
31283
31346
|
if (voiceSDK) {
|
|
31284
|
-
|
|
31347
|
+
_context5.n = 3;
|
|
31285
31348
|
break;
|
|
31286
31349
|
}
|
|
31287
31350
|
console.warn('TTPChatWidget: VoiceSDK not available');
|
|
31288
31351
|
throw new Error('VoiceSDK not available');
|
|
31289
31352
|
case 3:
|
|
31290
|
-
|
|
31291
|
-
|
|
31353
|
+
_context5.p = 3;
|
|
31354
|
+
_context5.n = 4;
|
|
31292
31355
|
return voiceSDK.injectData(data, _objectSpread(_objectSpread({}, options), {}, {
|
|
31293
31356
|
source: options.source || 'widget_programmatic'
|
|
31294
31357
|
}));
|
|
31295
31358
|
case 4:
|
|
31296
|
-
ack =
|
|
31297
|
-
return
|
|
31359
|
+
ack = _context5.v;
|
|
31360
|
+
return _context5.a(2, ack);
|
|
31298
31361
|
case 5:
|
|
31299
|
-
|
|
31300
|
-
|
|
31301
|
-
throw
|
|
31362
|
+
_context5.p = 5;
|
|
31363
|
+
_t = _context5.v;
|
|
31364
|
+
throw _t;
|
|
31302
31365
|
case 6:
|
|
31303
|
-
return
|
|
31366
|
+
return _context5.a(2);
|
|
31304
31367
|
}
|
|
31305
|
-
},
|
|
31368
|
+
}, _callee5, this, [[3, 5]]);
|
|
31306
31369
|
}));
|
|
31307
31370
|
function injectData(_x) {
|
|
31308
31371
|
return _injectData.apply(this, arguments);
|
|
@@ -31401,12 +31464,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
31401
31464
|
key: "_flushPendingClientTools",
|
|
31402
31465
|
value: function _flushPendingClientTools() {
|
|
31403
31466
|
var _this$voiceInterface0,
|
|
31404
|
-
|
|
31467
|
+
_this12 = this;
|
|
31405
31468
|
if (this._pendingClientTools && (_this$voiceInterface0 = this.voiceInterface) !== null && _this$voiceInterface0 !== void 0 && _this$voiceInterface0.sdk) {
|
|
31406
31469
|
this._pendingClientTools.forEach(function (_ref3) {
|
|
31407
31470
|
var name = _ref3.name,
|
|
31408
31471
|
handler = _ref3.handler;
|
|
31409
|
-
|
|
31472
|
+
_this12.voiceInterface.sdk.registerToolHandler(name, handler);
|
|
31410
31473
|
});
|
|
31411
31474
|
this._pendingClientTools = null;
|
|
31412
31475
|
console.log('TTPChatWidget: Flushed pending client tools');
|
|
@@ -31531,10 +31594,13 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
31531
31594
|
}, {
|
|
31532
31595
|
key: "generateHTML",
|
|
31533
31596
|
value: function generateHTML() {
|
|
31534
|
-
var _this$config$panel, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
|
|
31597
|
+
var _this$config$panel, _this$config$behavior, _this$config$sendButt, _this$config$panel2, _this$config$sendButt2, _this$config$panel3, _this$config$sendButt3, _this$config$panel4, _this$config$sendButt4, _this$config$panel5;
|
|
31535
31598
|
// Use text config, fallback to panel config, then translation, then default
|
|
31536
31599
|
var inputPlaceholder = this.config.inputPlaceholder || ((_this$config$panel = this.config.panel) === null || _this$config$panel === void 0 ? void 0 : _this$config$panel.inputPlaceholder) || this.t('typeMessage') || 'Type your message...';
|
|
31537
|
-
|
|
31600
|
+
var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
|
|
31601
|
+
var backArrow = this.config.direction === 'rtl' ? '→' : '←';
|
|
31602
|
+
var backBar = unifiedMode ? "\n <div class=\"text-interface-top-bar\">\n <button type=\"button\" class=\"text-interface-back-btn\" id=\"textUnifiedBackBtn\" aria-label=\"".concat(this.t('back'), "\">\n <span class=\"text-interface-back-icon\" aria-hidden=\"true\">").concat(backArrow, "</span>\n <span class=\"text-interface-back-label\">").concat(this.t('back'), "</span>\n </button>\n </div>") : '';
|
|
31603
|
+
return "<div class=\"text-interface\" id=\"textInterface\">\n ".concat(backBar, "\n <div class=\"messages-container\" id=\"messagesContainer\">\n <div class=\"empty-state\">\n <div class=\"empty-state-icon\">\uD83D\uDCAC</div>\n <div class=\"empty-state-title\">").concat(this.t('hello'), "</div>\n <div class=\"empty-state-text\">").concat(this.t('sendMessage'), "</div>\n </div>\n </div>\n <div class=\"input-container\">\n <div class=\"input-wrapper\" style=\"flex:1;\">\n <textarea class=\"message-input\" id=\"messageInput\" placeholder=\"").concat(inputPlaceholder, "\" rows=\"1\" dir=\"").concat(this.config.direction || 'ltr', "\"></textarea>\n </div>\n <button class=\"send-button\" id=\"sendButton\" aria-label=\"").concat(this.t('sendMessageAria'), "\">").concat(this.config.sendButtonText || '➤', "</button>\n ").concat((_this$config$sendButt = this.config.sendButtonHint) !== null && _this$config$sendButt !== void 0 && _this$config$sendButt.text || (_this$config$panel2 = this.config.panel) !== null && _this$config$panel2 !== void 0 && (_this$config$panel2 = _this$config$panel2.sendButtonHint) !== null && _this$config$panel2 !== void 0 && _this$config$panel2.text ? "\n <div class=\"send-button-hint\" style=\"color: ".concat(((_this$config$sendButt2 = this.config.sendButtonHint) === null || _this$config$sendButt2 === void 0 ? void 0 : _this$config$sendButt2.color) || ((_this$config$panel3 = this.config.panel) === null || _this$config$panel3 === void 0 || (_this$config$panel3 = _this$config$panel3.sendButtonHint) === null || _this$config$panel3 === void 0 ? void 0 : _this$config$panel3.color) || '#6B7280', "; font-size: ").concat(((_this$config$sendButt3 = this.config.sendButtonHint) === null || _this$config$sendButt3 === void 0 ? void 0 : _this$config$sendButt3.fontSize) || ((_this$config$panel4 = this.config.panel) === null || _this$config$panel4 === void 0 || (_this$config$panel4 = _this$config$panel4.sendButtonHint) === null || _this$config$panel4 === void 0 ? void 0 : _this$config$panel4.fontSize) || '12px', "; text-align: center; margin-top: 4px;\">\n ").concat(((_this$config$sendButt4 = this.config.sendButtonHint) === null || _this$config$sendButt4 === void 0 ? void 0 : _this$config$sendButt4.text) || ((_this$config$panel5 = this.config.panel) === null || _this$config$panel5 === void 0 || (_this$config$panel5 = _this$config$panel5.sendButtonHint) === null || _this$config$panel5 === void 0 ? void 0 : _this$config$panel5.text), "\n </div>\n ") : '', "\n </div>\n </div>");
|
|
31538
31604
|
}
|
|
31539
31605
|
|
|
31540
31606
|
/**
|
|
@@ -31563,7 +31629,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
31563
31629
|
|
|
31564
31630
|
// Add !important to display rules when not using Shadow DOM (to override theme CSS)
|
|
31565
31631
|
var important = this.config.useShadowDOM === false ? ' !important' : '';
|
|
31566
|
-
return "\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1".concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: #f8fafc").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: #64748b").concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 48px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 20px").concat(important, "; font-weight: 700").concat(important, "; color: #334155").concat(important, "; }\n .empty-state-text { font-size: 13px").concat(important, "; max-width: 280px").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n gap: 8px").concat(important, "; \n padding: 4px 0").concat(important, "; \n max-width: 100%").concat(important, "; \n align-items: center").concat(important, "; \n }\n .message.edge-left { flex-direction: row").concat(important, "; }\n .message.edge-right { flex-direction: row-reverse").concat(important, "; }\n .message-bubble { \n padding: 12px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize, "; \n word-wrap: break-word").concat(important, "; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, "; \n direction: ").concat(this.config.direction || 'ltr', ";\n }\n .message.user .message-bubble { \n background: ").concat(messages.userBackgroundColor).concat(important, "; \n color: ").concat(messages.userTextColor || messages.textColor).concat(important, "; \n }\n .message.agent .message-bubble { \n background: ").concat(messages.agentBackgroundColor).concat(important, "; \n color: ").concat(messages.agentTextColor || messages.textColor).concat(important, "; \n }\n .message.user { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-start' : 'flex-end').concat(important, "; \n }\n .message.agent { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start').concat(important, "; \n }\n .message .message-bubble { \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', " !important; \n }\n ").concat(this.config.direction === 'rtl' ? "\n .message-bubble {\n text-align: right !important;\n }\n " : '', "\n .message-avatar { \n width: 20px").concat(important, "; \n height: 20px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: 18px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n }\n .message-avatar.user { background: transparent").concat(important, "; }\n .message-avatar.agent { background: transparent").concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: #FFFFFF").concat(important, ";\n border-top: 1px solid #E5E7EB").concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row').concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: 32px").concat(important, ";\n max-height: 120px").concat(important, ";\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit").concat(important, ";\n line-height: 1.3").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor).concat(important, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(sendButtonColor, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '18px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3)").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: #64748b").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px").concat(important, ";\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B").concat(important, ";\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: 14px").concat(important, ";\n padding: 10px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 40px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 18px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 12px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: 13px").concat(important, ";\n padding: 8px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
|
|
31632
|
+
return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 10px 12px 8px").concat(important, ";\n border-bottom: 1px solid #E5E7EB").concat(important, ";\n background: #FFFFFF").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n .text-interface-back-btn {\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 6px 10px").concat(important, ";\n margin: 0").concat(important, ";\n border: none").concat(important, ";\n border-radius: 8px").concat(important, ";\n background: transparent").concat(important, ";\n color: #475569").concat(important, ";\n font-size: 14px").concat(important, ";\n font-weight: 600").concat(important, ";\n cursor: pointer").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .text-interface-back-btn:hover {\n background: #f1f5f9").concat(important, ";\n color: #334155").concat(important, ";\n }\n .text-interface-back-icon {\n font-size: 16px").concat(important, ";\n line-height: 1").concat(important, ";\n }\n .text-interface-back-label {\n line-height: 1.2").concat(important, ";\n }\n /* Messages container using new classes */\n #messagesContainer { \n flex: 1").concat(important, "; \n overflow-y: auto").concat(important, "; \n overflow-x: hidden").concat(important, "; \n padding: 20px").concat(important, "; \n background: #f8fafc").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n gap: 16px").concat(important, "; \n min-height: 0").concat(important, "; \n }\n .empty-state { \n flex: 1").concat(important, "; \n display: flex").concat(important, "; \n flex-direction: column").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n gap: 12px").concat(important, "; \n color: #64748b").concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 48px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 20px").concat(important, "; font-weight: 700").concat(important, "; color: #334155").concat(important, "; }\n .empty-state-text { font-size: 13px").concat(important, "; max-width: 280px").concat(important, "; }\n\n .text-interface { \n display: none").concat(important, "; \n flex: 1").concat(important, "; \n flex-direction: column").concat(important, "; \n min-height: 0").concat(important, "; \n overflow: hidden").concat(important, "; \n }\n .text-interface.active { display: flex").concat(important, "; }\n \n .message { \n display: flex").concat(important, "; \n gap: 8px").concat(important, "; \n padding: 4px 0").concat(important, "; \n max-width: 100%").concat(important, "; \n align-items: center").concat(important, "; \n }\n .message.edge-left { flex-direction: row").concat(important, "; }\n .message.edge-right { flex-direction: row-reverse").concat(important, "; }\n .message-bubble { \n padding: 12px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize, "; \n word-wrap: break-word").concat(important, "; \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, "; \n direction: ").concat(this.config.direction || 'ltr', ";\n }\n .message.user .message-bubble { \n background: ").concat(messages.userBackgroundColor).concat(important, "; \n color: ").concat(messages.userTextColor || messages.textColor).concat(important, "; \n }\n .message.agent .message-bubble { \n background: ").concat(messages.agentBackgroundColor).concat(important, "; \n color: ").concat(messages.agentTextColor || messages.textColor).concat(important, "; \n }\n .message.user { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-start' : 'flex-end').concat(important, "; \n }\n .message.agent { \n align-self: ").concat(this.config.direction === 'rtl' ? 'flex-end' : 'flex-start').concat(important, "; \n }\n .message .message-bubble { \n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left', " !important; \n }\n ").concat(this.config.direction === 'rtl' ? "\n .message-bubble {\n text-align: right !important;\n }\n " : '', "\n .message-avatar { \n width: 20px").concat(important, "; \n height: 20px").concat(important, "; \n display: flex").concat(important, "; \n align-items: center").concat(important, "; \n justify-content: center").concat(important, "; \n flex-shrink: 0").concat(important, "; \n color: inherit").concat(important, "; \n font-size: 18px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n }\n .message-avatar.user { background: transparent").concat(important, "; }\n .message-avatar.agent { background: transparent").concat(important, "; }\n \n .message.system {\n background: ").concat(messages.systemBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n .message.error {\n background: ").concat(messages.errorBackgroundColor, ";\n align-self: flex-start").concat(important, ";\n }\n \n .input-container {\n display: flex").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 12px 16px").concat(important, ";\n background: #FFFFFF").concat(important, ";\n border-top: 1px solid #E5E7EB").concat(important, ";\n align-items: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n flex-direction: ").concat(this.config.direction === 'rtl' ? 'row-reverse' : 'row').concat(important, ";\n }\n \n .input-wrapper {\n position: relative").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .message-input {\n width: 100%").concat(important, ";\n min-height: 32px").concat(important, ";\n max-height: 120px").concat(important, ";\n padding: ").concat(inputPadding, ";\n border: 1px solid ").concat(inputBorderColor, ";\n border-radius: ").concat(inputBorderRadius, "px;\n font-size: ").concat(inputFontSize, ";\n font-family: inherit").concat(important, ";\n line-height: 1.3").concat(important, ";\n resize: none").concat(important, ";\n overflow-y: auto").concat(important, ";\n background: ").concat(inputBackgroundColor, ";\n color: ").concat(inputTextColor, ";\n vertical-align: top").concat(important, ";\n margin: 0").concat(important, ";\n display: block").concat(important, ";\n white-space: pre-wrap").concat(important, ";\n word-wrap: break-word").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n direction: ").concat(this.config.direction || 'ltr', ";\n -webkit-appearance: none").concat(important, ";\n appearance: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n \n .message-input:focus {\n outline: none").concat(important, ";\n border-color: ").concat(inputFocusColor, ";\n background: ").concat(inputBackgroundColor === '#FFFFFF' ? '#FFFFFF' : inputBackgroundColor).concat(important, ";\n box-shadow: 0 0 0 3px ").concat(inputFocusColor, "33;\n }\n \n .message-input::placeholder {\n color: #9CA3AF").concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(sendButtonColor, ";\n color: ").concat(sendButtonTextColor, ";\n font-size: ").concat(this.config.sendButtonFontSize || ((_this$config$panel15 = this.config.panel) === null || _this$config$panel15 === void 0 ? void 0 : _this$config$panel15.sendButtonFontSize) || '18px', ";\n font-weight: ").concat(this.config.sendButtonFontWeight || ((_this$config$panel16 = this.config.panel) === null || _this$config$panel16 === void 0 ? void 0 : _this$config$panel16.sendButtonFontWeight) || '500', ";\n cursor: pointer").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n box-shadow: 0 4px 12px rgba(124, 60, 237, 0.3)").concat(important, ";\n }\n \n .send-button:hover:not(:disabled) {\n background: ").concat(sendButtonHoverColor, ";\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 6px 16px rgba(124, 60, 237, 0.4)").concat(important, ";\n }\n \n .send-button-hint {\n width: 100%").concat(important, ";\n text-align: center").concat(important, ";\n margin-top: 4px").concat(important, ";\n }\n \n .send-button:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n \n .typing-indicator {\n display: inline-flex").concat(important, ";\n gap: 4px").concat(important, ";\n align-items: center").concat(important, ";\n }\n \n .typing-dot {\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: #64748b").concat(important, ";\n animation: typingDot 1.4s ease-in-out infinite").concat(important, ";\n }\n \n .typing-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .typing-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n \n @keyframes typingDot {\n 0%, 60%, 100% { transform: translateY(0); opacity: 0.7; }\n 30% { transform: translateY(-8px); opacity: 1; }\n }\n \n .error-message {\n padding: 12px").concat(important, ";\n background: ").concat(messages.errorBackgroundColor, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: #991B1B").concat(important, ";\n font-size: ").concat(messages.fontSize, ";\n margin: 8px 0").concat(important, ";\n }\n \n @media (max-width: 768px) {\n #messagesContainer {\n padding: 12px").concat(important, ";\n gap: 12px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 85%").concat(important, ";\n font-size: 14px").concat(important, ";\n padding: 10px").concat(important, ";\n }\n \n .text-input-container {\n padding: 10px").concat(important, ";\n gap: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important; /* Prevents iOS zoom on focus */\n padding: 10px 14px").concat(important, ";\n min-height: 44px").concat(important, ";\n }\n \n #text-chat-send {\n min-width: 56px").concat(important, ";\n min-height: 44px").concat(important, ";\n width: 56px").concat(important, ";\n height: 44px").concat(important, ";\n }\n \n .empty-state-icon {\n font-size: 40px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 18px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 12px").concat(important, ";\n }\n }\n \n @media (max-width: 480px) {\n #messagesContainer {\n padding: 10px").concat(important, ";\n gap: 10px").concat(important, ";\n }\n \n .message-bubble {\n max-width: 90%").concat(important, ";\n font-size: 13px").concat(important, ";\n padding: 8px").concat(important, ";\n }\n \n .text-input-container {\n padding: 8px").concat(important, ";\n }\n \n #text-chat-input {\n font-size: 16px !important;\n padding: 8px 12px").concat(important, ";\n }\n }\n ");
|
|
31567
31633
|
}
|
|
31568
31634
|
|
|
31569
31635
|
/**
|
|
@@ -31964,16 +32030,17 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
31964
32030
|
/* harmony export */ VoiceInterface: () => (/* binding */ VoiceInterface)
|
|
31965
32031
|
/* harmony export */ });
|
|
31966
32032
|
/* harmony import */ var _index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../index.js */ "./src/index.js");
|
|
31967
|
-
/* harmony import */ var
|
|
31968
|
-
/* harmony import */ var
|
|
31969
|
-
/* harmony import */ var
|
|
31970
|
-
/* harmony import */ var
|
|
31971
|
-
/* harmony import */ var
|
|
31972
|
-
/* harmony import */ var
|
|
31973
|
-
/* harmony import */ var
|
|
31974
|
-
/* harmony import */ var
|
|
31975
|
-
/* harmony import */ var
|
|
31976
|
-
/* harmony import */ var
|
|
32033
|
+
/* harmony import */ var _core_AudioRecorder_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../core/AudioRecorder.js */ "./src/core/AudioRecorder.js");
|
|
32034
|
+
/* harmony import */ var _shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../shared/MicPermissionUtils.js */ "./src/shared/MicPermissionUtils.js");
|
|
32035
|
+
/* harmony import */ var _shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../shared/applyDelay.js */ "./src/shared/applyDelay.js");
|
|
32036
|
+
/* harmony import */ var _shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../shared/MicPermissionModals.js */ "./src/shared/MicPermissionModals.js");
|
|
32037
|
+
/* harmony import */ var _voice_templates_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./voice/templates.js */ "./src/widget/voice/templates.js");
|
|
32038
|
+
/* harmony import */ var _voice_styles_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./voice/styles.js */ "./src/widget/voice/styles.js");
|
|
32039
|
+
/* harmony import */ var _voice_transcript_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./voice/transcript.js */ "./src/widget/voice/transcript.js");
|
|
32040
|
+
/* harmony import */ var _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./voice/textHandlers.js */ "./src/widget/voice/textHandlers.js");
|
|
32041
|
+
/* harmony import */ var _voice_handlers_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./voice/handlers.js */ "./src/widget/voice/handlers.js");
|
|
32042
|
+
/* harmony import */ var _voice_desktop_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./voice/desktop.js */ "./src/widget/voice/desktop.js");
|
|
32043
|
+
/* harmony import */ var _voice_mobile_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./voice/mobile.js */ "./src/widget/voice/mobile.js");
|
|
31977
32044
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
31978
32045
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
31979
32046
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
@@ -32001,9 +32068,10 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
32001
32068
|
|
|
32002
32069
|
|
|
32003
32070
|
|
|
32071
|
+
|
|
32004
32072
|
var VoiceInterface = /*#__PURE__*/function () {
|
|
32005
32073
|
function VoiceInterface(config) {
|
|
32006
|
-
var _config$agentSettings;
|
|
32074
|
+
var _this$config$behavior, _config$agentSettings;
|
|
32007
32075
|
_classCallCheck(this, VoiceInterface);
|
|
32008
32076
|
this.config = config;
|
|
32009
32077
|
this.audioStream = null;
|
|
@@ -32016,9 +32084,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32016
32084
|
this.shadowRoot = config.shadowRoot || document;
|
|
32017
32085
|
// Text SDK reference for sending text messages during voice calls
|
|
32018
32086
|
this.textSDK = config.textSDK || null;
|
|
32019
|
-
// Mobile
|
|
32020
|
-
this.deviceInfo = (0,
|
|
32021
|
-
this.
|
|
32087
|
+
// Mobile voice UI: native iOS/Android, or narrow + touch (WebViews with desktop UA)
|
|
32088
|
+
this.deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
|
|
32089
|
+
var explicitMobileVoice = this.config.mobileVoiceUI !== undefined ? this.config.mobileVoiceUI : (_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mobileVoiceUI;
|
|
32090
|
+
this.isMobile = explicitMobileVoice === true ? true : explicitMobileVoice === false ? false : (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.shouldUseMobileVoiceCallUI)();
|
|
32022
32091
|
// Conversation messages for mobile UI (owned by mobile module, initialized there)
|
|
32023
32092
|
// Desktop conversation state
|
|
32024
32093
|
this.conversationExpanded = false;
|
|
@@ -32057,13 +32126,13 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32057
32126
|
});
|
|
32058
32127
|
|
|
32059
32128
|
// Initialize modules with context (delegation pattern)
|
|
32060
|
-
this.templates = new
|
|
32061
|
-
this.styles = new
|
|
32062
|
-
this.transcript = new
|
|
32063
|
-
this.textHandlers = new
|
|
32064
|
-
this.handlers = new
|
|
32065
|
-
this.desktop = new
|
|
32066
|
-
this.mobile = new
|
|
32129
|
+
this.templates = new _voice_templates_js__WEBPACK_IMPORTED_MODULE_5__.Templates(this);
|
|
32130
|
+
this.styles = new _voice_styles_js__WEBPACK_IMPORTED_MODULE_6__.Styles(this);
|
|
32131
|
+
this.transcript = new _voice_transcript_js__WEBPACK_IMPORTED_MODULE_7__.Transcript(this);
|
|
32132
|
+
this.textHandlers = new _voice_textHandlers_js__WEBPACK_IMPORTED_MODULE_8__.TextHandlers(this);
|
|
32133
|
+
this.handlers = new _voice_handlers_js__WEBPACK_IMPORTED_MODULE_9__.Handlers(this);
|
|
32134
|
+
this.desktop = new _voice_desktop_js__WEBPACK_IMPORTED_MODULE_10__.Desktop(this);
|
|
32135
|
+
this.mobile = new _voice_mobile_js__WEBPACK_IMPORTED_MODULE_11__.Mobile(this);
|
|
32067
32136
|
|
|
32068
32137
|
// Setup SDK event handlers
|
|
32069
32138
|
this.setupSDKEventHandlers();
|
|
@@ -32140,27 +32209,8 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32140
32209
|
}
|
|
32141
32210
|
_this._pendingUserTranscriptFrame = requestAnimationFrame(function () {
|
|
32142
32211
|
_this._pendingUserTranscriptFrame = null;
|
|
32143
|
-
var
|
|
32144
|
-
|
|
32145
|
-
var mobileTranscriptText = mobileBar.querySelector('#mobileTranscriptText');
|
|
32146
|
-
if (mobileTranscriptText) {
|
|
32147
|
-
mobileTranscriptText.textContent = 'You: ' + text;
|
|
32148
|
-
mobileTranscriptText.style.color = '#fde68a';
|
|
32149
|
-
}
|
|
32150
|
-
} else {
|
|
32151
|
-
var liveTextCollapsed = _this.shadowRoot.getElementById('liveTextCollapsed');
|
|
32152
|
-
if (liveTextCollapsed) {
|
|
32153
|
-
liveTextCollapsed.textContent = '';
|
|
32154
|
-
liveTextCollapsed.classList.remove('muted');
|
|
32155
|
-
liveTextCollapsed.style.color = '#e8e4f0';
|
|
32156
|
-
var label = document.createElement('span');
|
|
32157
|
-
label.style.fontWeight = '600';
|
|
32158
|
-
label.style.color = '#c4b5fd';
|
|
32159
|
-
label.textContent = 'You: ';
|
|
32160
|
-
liveTextCollapsed.appendChild(label);
|
|
32161
|
-
liveTextCollapsed.appendChild(document.createTextNode(text));
|
|
32162
|
-
}
|
|
32163
|
-
}
|
|
32212
|
+
var userPrefix = _this.getUserTranscriptPrefix();
|
|
32213
|
+
_this._renderUserLiveTranscriptSnippet(userPrefix, text);
|
|
32164
32214
|
});
|
|
32165
32215
|
|
|
32166
32216
|
// History update is synchronous (small, only on final)
|
|
@@ -32378,6 +32428,64 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32378
32428
|
// Fall back to translation system
|
|
32379
32429
|
return this.t(translationKey);
|
|
32380
32430
|
}
|
|
32431
|
+
|
|
32432
|
+
/** Prefix before interim/final user speech in the live transcript strip (not history bubbles). */
|
|
32433
|
+
}, {
|
|
32434
|
+
key: "getUserTranscriptPrefix",
|
|
32435
|
+
value: function getUserTranscriptPrefix() {
|
|
32436
|
+
return this.getText('userTranscriptPrefix', 'userTranscriptPrefix');
|
|
32437
|
+
}
|
|
32438
|
+
|
|
32439
|
+
/**
|
|
32440
|
+
* Live user STT line: correct RTL/LTR order, visible gap after "אתה:", and sensible ? placement (utterance in dir=auto).
|
|
32441
|
+
*/
|
|
32442
|
+
}, {
|
|
32443
|
+
key: "_renderUserLiveTranscriptSnippet",
|
|
32444
|
+
value: function _renderUserLiveTranscriptSnippet(userPrefix, text) {
|
|
32445
|
+
var isRtl = this.config.direction === 'rtl';
|
|
32446
|
+
var raw = userPrefix !== undefined && userPrefix !== null ? String(userPrefix) : '';
|
|
32447
|
+
var trimmedPrefix = raw.replace(/\s+$/, '');
|
|
32448
|
+
var sepChar = isRtl ? "\xA0" : ' ';
|
|
32449
|
+
var mobileBar = document.getElementById('mobile-voice-call-bar-container');
|
|
32450
|
+
if (mobileBar) {
|
|
32451
|
+
var el = mobileBar.querySelector('#mobileTranscriptText');
|
|
32452
|
+
if (!el) return;
|
|
32453
|
+
el.textContent = '';
|
|
32454
|
+
el.setAttribute('dir', isRtl ? 'rtl' : 'ltr');
|
|
32455
|
+
if (trimmedPrefix) {
|
|
32456
|
+
var prefixSpan = document.createElement('span');
|
|
32457
|
+
prefixSpan.style.fontWeight = '600';
|
|
32458
|
+
prefixSpan.style.color = '#c4b5fd';
|
|
32459
|
+
prefixSpan.textContent = trimmedPrefix;
|
|
32460
|
+
el.appendChild(prefixSpan);
|
|
32461
|
+
el.appendChild(document.createTextNode(sepChar));
|
|
32462
|
+
}
|
|
32463
|
+
var utter = document.createElement('span');
|
|
32464
|
+
utter.setAttribute('dir', 'auto');
|
|
32465
|
+
utter.textContent = text;
|
|
32466
|
+
el.appendChild(utter);
|
|
32467
|
+
el.style.color = '#fde68a';
|
|
32468
|
+
return;
|
|
32469
|
+
}
|
|
32470
|
+
var liveTextCollapsed = this.shadowRoot.getElementById('liveTextCollapsed');
|
|
32471
|
+
if (!liveTextCollapsed) return;
|
|
32472
|
+
liveTextCollapsed.textContent = '';
|
|
32473
|
+
liveTextCollapsed.classList.remove('muted');
|
|
32474
|
+
liveTextCollapsed.style.color = '#e8e4f0';
|
|
32475
|
+
liveTextCollapsed.setAttribute('dir', isRtl ? 'rtl' : 'ltr');
|
|
32476
|
+
if (trimmedPrefix) {
|
|
32477
|
+
var _prefixSpan = document.createElement('span');
|
|
32478
|
+
_prefixSpan.className = 'name ttp-user-live-prefix';
|
|
32479
|
+
_prefixSpan.textContent = trimmedPrefix;
|
|
32480
|
+
liveTextCollapsed.appendChild(_prefixSpan);
|
|
32481
|
+
liveTextCollapsed.appendChild(document.createTextNode(sepChar));
|
|
32482
|
+
}
|
|
32483
|
+
var utterance = document.createElement('span');
|
|
32484
|
+
utterance.className = 'ttp-user-live-utterance';
|
|
32485
|
+
utterance.setAttribute('dir', 'auto');
|
|
32486
|
+
utterance.textContent = text;
|
|
32487
|
+
liveTextCollapsed.appendChild(utterance);
|
|
32488
|
+
}
|
|
32381
32489
|
}, {
|
|
32382
32490
|
key: "getTooltip",
|
|
32383
32491
|
value: function getTooltip(key) {
|
|
@@ -32585,7 +32693,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32585
32693
|
value: (function () {
|
|
32586
32694
|
var _startVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
|
|
32587
32695
|
var _this2 = this;
|
|
32588
|
-
var permissionState, deviceInfo, idleState, activeState;
|
|
32696
|
+
var permissionState, deviceInfo, idleState, activeState, mobilePanelPrePrompt, mobilePanelWasOpen;
|
|
32589
32697
|
return _regenerator().w(function (_context4) {
|
|
32590
32698
|
while (1) switch (_context4.n) {
|
|
32591
32699
|
case 0:
|
|
@@ -32600,7 +32708,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32600
32708
|
|
|
32601
32709
|
// Check permission state first
|
|
32602
32710
|
_context4.n = 2;
|
|
32603
|
-
return (0,
|
|
32711
|
+
return (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.checkPermissionState)();
|
|
32604
32712
|
case 2:
|
|
32605
32713
|
permissionState = _context4.v;
|
|
32606
32714
|
console.log("\uD83D\uDCCB Current permission state: ".concat(permissionState));
|
|
@@ -32613,8 +32721,8 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32613
32721
|
console.log('🚫 Permission is denied, showing blocked modal...');
|
|
32614
32722
|
// Reset connecting state since we're not proceeding
|
|
32615
32723
|
this.resetConnectingState();
|
|
32616
|
-
deviceInfo = (0,
|
|
32617
|
-
(0,
|
|
32724
|
+
deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
|
|
32725
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
|
|
32618
32726
|
// Modal closed - user can try again
|
|
32619
32727
|
console.log('Blocked modal closed');
|
|
32620
32728
|
}, function () {
|
|
@@ -32629,14 +32737,28 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32629
32737
|
break;
|
|
32630
32738
|
}
|
|
32631
32739
|
console.log('📋 Permission is in prompt state, showing pre-prompt modal with call view...');
|
|
32632
|
-
|
|
32633
|
-
// Switch UI to active call view so it's visible behind the modal
|
|
32634
32740
|
idleState = this.shadowRoot.getElementById('voiceIdleState');
|
|
32635
|
-
activeState = this.shadowRoot.getElementById('voiceActiveState');
|
|
32636
|
-
|
|
32637
|
-
|
|
32741
|
+
activeState = this.shadowRoot.getElementById('voiceActiveState'); // Desktop: show in-panel active call behind the semi-transparent overlay.
|
|
32742
|
+
// Mobile: do NOT show #voiceActiveState — it is only a non-fixed placeholder; flex layout
|
|
32743
|
+
// pins the fake bar to the top of the panel. Real chrome is body-fixed in proceedWithVoiceCall().
|
|
32744
|
+
mobilePanelPrePrompt = null;
|
|
32745
|
+
mobilePanelWasOpen = false;
|
|
32746
|
+
if (this.isMobile) {
|
|
32747
|
+
if (idleState) idleState.style.display = 'none';
|
|
32748
|
+
if (activeState) activeState.style.display = 'none';
|
|
32749
|
+
// Empty open panel reads as a dark "shadow" behind the sheet — hide it until cancel or call end
|
|
32750
|
+
mobilePanelPrePrompt = this.shadowRoot.getElementById('text-chat-panel') || document.getElementById('text-chat-panel');
|
|
32751
|
+
if (mobilePanelPrePrompt) {
|
|
32752
|
+
mobilePanelWasOpen = mobilePanelPrePrompt.classList.contains('open');
|
|
32753
|
+
mobilePanelPrePrompt.classList.remove('open');
|
|
32754
|
+
mobilePanelPrePrompt.style.display = 'none';
|
|
32755
|
+
}
|
|
32756
|
+
} else {
|
|
32757
|
+
if (idleState) idleState.style.display = 'none';
|
|
32758
|
+
if (activeState) activeState.style.display = 'flex';
|
|
32759
|
+
}
|
|
32638
32760
|
return _context4.a(2, new Promise(function (resolve, reject) {
|
|
32639
|
-
(0,
|
|
32761
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showPrePromptModal)(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
32640
32762
|
var _t;
|
|
32641
32763
|
return _regenerator().w(function (_context3) {
|
|
32642
32764
|
while (1) switch (_context3.p = _context3.n) {
|
|
@@ -32662,6 +32784,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32662
32784
|
// Revert UI back to idle state
|
|
32663
32785
|
if (idleState) idleState.style.display = 'flex';
|
|
32664
32786
|
if (activeState) activeState.style.display = 'none';
|
|
32787
|
+
if (_this2.isMobile && mobilePanelPrePrompt) {
|
|
32788
|
+
mobilePanelPrePrompt.style.display = '';
|
|
32789
|
+
if (mobilePanelWasOpen) mobilePanelPrePrompt.classList.add('open');
|
|
32790
|
+
}
|
|
32665
32791
|
_this2.resetConnectingState();
|
|
32666
32792
|
reject(new Error('Call cancelled by user'));
|
|
32667
32793
|
});
|
|
@@ -32682,17 +32808,52 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32682
32808
|
/**
|
|
32683
32809
|
* Proceed with voice call after permission check/pre-prompt
|
|
32684
32810
|
*/
|
|
32811
|
+
/**
|
|
32812
|
+
* Show server-driven disclaimer and send disclaimer_ack (voice protocol).
|
|
32813
|
+
*/
|
|
32685
32814
|
)
|
|
32686
32815
|
}, {
|
|
32687
|
-
key: "
|
|
32816
|
+
key: "resolveServerDisclaimer",
|
|
32688
32817
|
value: (function () {
|
|
32689
|
-
var
|
|
32690
|
-
var
|
|
32691
|
-
var
|
|
32818
|
+
var _resolveServerDisclaimer = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(voiceSDK) {
|
|
32819
|
+
var _payload$texts;
|
|
32820
|
+
var payload, texts;
|
|
32692
32821
|
return _regenerator().w(function (_context5) {
|
|
32693
|
-
while (1) switch (_context5.
|
|
32822
|
+
while (1) switch (_context5.n) {
|
|
32694
32823
|
case 0:
|
|
32695
|
-
|
|
32824
|
+
payload = voiceSDK.lastDisclaimerPayload;
|
|
32825
|
+
texts = payload !== null && payload !== void 0 && (_payload$texts = payload.texts) !== null && _payload$texts !== void 0 && _payload$texts.length ? payload.texts : ['Please confirm to continue.'];
|
|
32826
|
+
return _context5.a(2, new Promise(function (resolve, reject) {
|
|
32827
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showServerDisclaimerModal)({
|
|
32828
|
+
texts: texts,
|
|
32829
|
+
onAccept: function onAccept() {
|
|
32830
|
+
voiceSDK.sendDisclaimerAck(true);
|
|
32831
|
+
resolve();
|
|
32832
|
+
},
|
|
32833
|
+
onCancel: function onCancel() {
|
|
32834
|
+
voiceSDK.sendDisclaimerAck(false);
|
|
32835
|
+
reject(new Error('DISCLAIMER_DECLINED'));
|
|
32836
|
+
}
|
|
32837
|
+
});
|
|
32838
|
+
}));
|
|
32839
|
+
}
|
|
32840
|
+
}, _callee5);
|
|
32841
|
+
}));
|
|
32842
|
+
function resolveServerDisclaimer(_x3) {
|
|
32843
|
+
return _resolveServerDisclaimer.apply(this, arguments);
|
|
32844
|
+
}
|
|
32845
|
+
return resolveServerDisclaimer;
|
|
32846
|
+
}())
|
|
32847
|
+
}, {
|
|
32848
|
+
key: "proceedWithVoiceCall",
|
|
32849
|
+
value: function () {
|
|
32850
|
+
var _proceedWithVoiceCall = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
32851
|
+
var _this3 = this;
|
|
32852
|
+
var isResumeCall, panel, header, toggleText, originalSection, compactSection, idleState, _panel, fallbackPanel, preliminaryInputStream, _this$config$inputFor, primeSr, floatingButton, fallbackButton, mobileFabGrant, existingBar, _floatingButton, _fallbackButton, mobileFabDeny, _idleState, _panel2, _fallbackPanel, deviceInfo, _idleState2, activeState, voiceInterface, _this$config$connecti, delayConfig, connected, serverRejected, originalOnError, originalOnDisconnected, attempts, serverDisclaimerHandled, vs, streamToUse, _this$sdk$voiceSDK, error, _existingBar, _existingBar2, _idleState3, _panel3, _fallbackPanel2, _floatingButton2, _fallbackButton2, updateTimer, _streamToUse, _existingBar3, _existingBar4, _idleState4, _panel4, _fallbackPanel3, _floatingButton3, _fallbackButton3, _updateTimer, _deviceInfo, _t2, _t3, _t4, _t5, _t6, _t7, _t8;
|
|
32853
|
+
return _regenerator().w(function (_context6) {
|
|
32854
|
+
while (1) switch (_context6.p = _context6.n) {
|
|
32855
|
+
case 0:
|
|
32856
|
+
_context6.p = 0;
|
|
32696
32857
|
// Clear conversation history for new calls (but preserve it for resume calls)
|
|
32697
32858
|
isResumeCall = this._resumeInfo !== null && this._resumeInfo !== undefined;
|
|
32698
32859
|
if (!isResumeCall) {
|
|
@@ -32728,7 +32889,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32728
32889
|
|
|
32729
32890
|
// First, handle UI state changes (but don't create mobile bar yet)
|
|
32730
32891
|
if (!this.isMobile) {
|
|
32731
|
-
|
|
32892
|
+
_context6.n = 6;
|
|
32732
32893
|
break;
|
|
32733
32894
|
}
|
|
32734
32895
|
// On mobile, hide widget panel immediately (but keep floating button visible)
|
|
@@ -32753,22 +32914,30 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32753
32914
|
}
|
|
32754
32915
|
}
|
|
32755
32916
|
|
|
32917
|
+
// Body-fixed bar must exist during the native browser mic prompt — otherwise the screen is blank
|
|
32918
|
+
this.showMobileCallBarAwaitingBrowserMic();
|
|
32919
|
+
|
|
32756
32920
|
// CRITICAL for mobile: Request permission BEFORE connecting to WebSocket
|
|
32757
32921
|
// This prevents the agent from starting to speak before permission is granted
|
|
32758
32922
|
// ELEVENLABS PATTERN: Minimal constraints for first getUserMedia, keep stream alive,
|
|
32759
32923
|
// pass it to AudioRecorder so we never call getUserMedia twice (iOS fails with 2 streams).
|
|
32760
32924
|
console.log('📱 Mobile device - requesting mic permission before connecting...');
|
|
32761
32925
|
preliminaryInputStream = null;
|
|
32762
|
-
|
|
32763
|
-
|
|
32926
|
+
_context6.p = 1;
|
|
32927
|
+
_context6.n = 2;
|
|
32764
32928
|
return navigator.mediaDevices.getUserMedia({
|
|
32765
32929
|
audio: true
|
|
32766
32930
|
});
|
|
32767
32931
|
case 2:
|
|
32768
|
-
preliminaryInputStream =
|
|
32932
|
+
preliminaryInputStream = _context6.v;
|
|
32769
32933
|
// DO NOT stop the stream here - keep it alive until startListening completes
|
|
32770
32934
|
this._preliminaryInputStream = preliminaryInputStream;
|
|
32771
32935
|
console.log('✅ Mobile: Microphone permission granted - keeping stream alive (ElevenLabs pattern)');
|
|
32936
|
+
primeSr = ((_this$config$inputFor = this.config.inputFormat) === null || _this$config$inputFor === void 0 ? void 0 : _this$config$inputFor.sampleRate) || this.config.sampleRate || 16000;
|
|
32937
|
+
_context6.n = 3;
|
|
32938
|
+
return _core_AudioRecorder_js__WEBPACK_IMPORTED_MODULE_1__["default"].primeSharedContext(primeSr);
|
|
32939
|
+
case 3:
|
|
32940
|
+
this.applyMobileBarConnectingCopy();
|
|
32772
32941
|
|
|
32773
32942
|
// NOW hide the floating button too (permission granted)
|
|
32774
32943
|
floatingButton = this.shadowRoot.getElementById('text-chat-button');
|
|
@@ -32784,11 +32953,11 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32784
32953
|
}
|
|
32785
32954
|
mobileFabGrant = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
32786
32955
|
if (mobileFabGrant) mobileFabGrant.style.display = 'none';
|
|
32787
|
-
|
|
32956
|
+
_context6.n = 5;
|
|
32788
32957
|
break;
|
|
32789
|
-
case
|
|
32790
|
-
|
|
32791
|
-
_t2 =
|
|
32958
|
+
case 4:
|
|
32959
|
+
_context6.p = 4;
|
|
32960
|
+
_t2 = _context6.v;
|
|
32792
32961
|
console.error('❌ Mobile: Permission denied before connecting:', _t2);
|
|
32793
32962
|
// Permission was denied - reset connecting state and restore UI
|
|
32794
32963
|
this.resetConnectingState();
|
|
@@ -32828,24 +32997,24 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32828
32997
|
}
|
|
32829
32998
|
|
|
32830
32999
|
// Show blocked modal
|
|
32831
|
-
deviceInfo = (0,
|
|
32832
|
-
(0,
|
|
33000
|
+
deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
|
|
33001
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
|
|
32833
33002
|
_this3.resetUIState();
|
|
32834
33003
|
}, function () {
|
|
32835
33004
|
window.location.reload();
|
|
32836
33005
|
});
|
|
32837
|
-
return
|
|
32838
|
-
case 4:
|
|
32839
|
-
_context5.n = 6;
|
|
32840
|
-
break;
|
|
33006
|
+
return _context6.a(2);
|
|
32841
33007
|
case 5:
|
|
33008
|
+
_context6.n = 7;
|
|
33009
|
+
break;
|
|
33010
|
+
case 6:
|
|
32842
33011
|
// Desktop: Reset connecting state, then hide idle state and show active state
|
|
32843
33012
|
this.resetConnectingState();
|
|
32844
33013
|
_idleState2 = this.shadowRoot.getElementById('voiceIdleState');
|
|
32845
33014
|
activeState = this.shadowRoot.getElementById('voiceActiveState');
|
|
32846
33015
|
if (_idleState2) _idleState2.style.display = 'none';
|
|
32847
33016
|
if (activeState) activeState.style.display = 'flex';
|
|
32848
|
-
case
|
|
33017
|
+
case 7:
|
|
32849
33018
|
voiceInterface = this.shadowRoot.getElementById('voiceInterface'); // Adjust sizes based on container dimensions
|
|
32850
33019
|
setTimeout(function () {
|
|
32851
33020
|
return _this3.adjustSizesForContainer();
|
|
@@ -32858,32 +33027,32 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32858
33027
|
|
|
32859
33028
|
// Connect using agentId + appId (URL built internally by SDK)
|
|
32860
33029
|
if (this.config.agentId) {
|
|
32861
|
-
|
|
33030
|
+
_context6.n = 8;
|
|
32862
33031
|
break;
|
|
32863
33032
|
}
|
|
32864
33033
|
throw new Error('agentId is required for voice calls');
|
|
32865
|
-
case
|
|
33034
|
+
case 8:
|
|
32866
33035
|
if (!(this.sdk && this.sdk.isConnected)) {
|
|
32867
|
-
|
|
33036
|
+
_context6.n = 12;
|
|
32868
33037
|
break;
|
|
32869
33038
|
}
|
|
32870
33039
|
console.log('🔄 SDK already connected, disconnecting for clean retry...');
|
|
32871
|
-
|
|
33040
|
+
_context6.p = 9;
|
|
32872
33041
|
this.sdk.disconnect();
|
|
32873
|
-
|
|
33042
|
+
_context6.n = 10;
|
|
32874
33043
|
return new Promise(function (resolve) {
|
|
32875
33044
|
return setTimeout(resolve, 100);
|
|
32876
33045
|
});
|
|
32877
|
-
case 9:
|
|
32878
|
-
_context5.n = 11;
|
|
32879
|
-
break;
|
|
32880
33046
|
case 10:
|
|
32881
|
-
|
|
32882
|
-
|
|
32883
|
-
console.warn('Warning: Error disconnecting existing connection:', _t3);
|
|
33047
|
+
_context6.n = 12;
|
|
33048
|
+
break;
|
|
32884
33049
|
case 11:
|
|
33050
|
+
_context6.p = 11;
|
|
33051
|
+
_t3 = _context6.v;
|
|
33052
|
+
console.warn('Warning: Error disconnecting existing connection:', _t3);
|
|
33053
|
+
case 12:
|
|
32885
33054
|
if (!this.isMobile) {
|
|
32886
|
-
|
|
33055
|
+
_context6.n = 13;
|
|
32887
33056
|
break;
|
|
32888
33057
|
}
|
|
32889
33058
|
delayConfig = (_this$config$connecti = this.config.connectionDelay) !== null && _this$config$connecti !== void 0 ? _this$config$connecti : {
|
|
@@ -32891,13 +33060,13 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32891
33060
|
android: 3000,
|
|
32892
33061
|
ios: 0
|
|
32893
33062
|
};
|
|
32894
|
-
|
|
32895
|
-
return (0,
|
|
32896
|
-
case 12:
|
|
32897
|
-
_context5.n = 13;
|
|
32898
|
-
return this.sdk.connect();
|
|
33063
|
+
_context6.n = 13;
|
|
33064
|
+
return (0,_shared_applyDelay_js__WEBPACK_IMPORTED_MODULE_3__.applyDelay)(delayConfig);
|
|
32899
33065
|
case 13:
|
|
32900
|
-
|
|
33066
|
+
_context6.n = 14;
|
|
33067
|
+
return this.sdk.connect();
|
|
33068
|
+
case 14:
|
|
33069
|
+
connected = _context6.v;
|
|
32901
33070
|
console.log('✅ Connected to WebSocket, connected:', connected);
|
|
32902
33071
|
|
|
32903
33072
|
// Set up text inject ack handler using EventEmitter pattern
|
|
@@ -32928,39 +33097,70 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32928
33097
|
// Wait for connection to be fully ready (for hello message exchange)
|
|
32929
33098
|
// Check both AgentSDK.isConnected and underlying VoiceSDK connection
|
|
32930
33099
|
attempts = 0;
|
|
32931
|
-
|
|
32932
|
-
|
|
32933
|
-
|
|
33100
|
+
serverDisclaimerHandled = false;
|
|
33101
|
+
case 15:
|
|
33102
|
+
if (!(attempts < 150)) {
|
|
33103
|
+
_context6.n = 25;
|
|
32934
33104
|
break;
|
|
32935
33105
|
}
|
|
32936
33106
|
if (!serverRejected) {
|
|
32937
|
-
|
|
33107
|
+
_context6.n = 16;
|
|
32938
33108
|
break;
|
|
32939
33109
|
}
|
|
32940
33110
|
console.log('🚫 Server rejected connection, aborting audio capture');
|
|
32941
33111
|
throw new Error('DOMAIN_NOT_WHITELISTED');
|
|
32942
|
-
case
|
|
33112
|
+
case 16:
|
|
32943
33113
|
if (!this.sdk.isConnected) {
|
|
32944
|
-
|
|
33114
|
+
_context6.n = 23;
|
|
32945
33115
|
break;
|
|
32946
33116
|
}
|
|
32947
|
-
|
|
32948
|
-
|
|
33117
|
+
vs = this.sdk.voiceSDK; // Verify WebSocket is open AND hello_ack has been received (input format negotiated)
|
|
33118
|
+
if (!(vs && vs.isConnected && vs.helloAckReceived && vs.websocket && vs.websocket.readyState === WebSocket.OPEN)) {
|
|
33119
|
+
_context6.n = 23;
|
|
32949
33120
|
break;
|
|
32950
33121
|
}
|
|
32951
|
-
|
|
32952
|
-
|
|
32953
|
-
|
|
33122
|
+
if (!(vs.disclaimersPending && !serverDisclaimerHandled)) {
|
|
33123
|
+
_context6.n = 22;
|
|
33124
|
+
break;
|
|
33125
|
+
}
|
|
33126
|
+
serverDisclaimerHandled = true;
|
|
33127
|
+
_context6.p = 17;
|
|
33128
|
+
_context6.n = 18;
|
|
33129
|
+
return this.resolveServerDisclaimer(vs);
|
|
33130
|
+
case 18:
|
|
33131
|
+
_context6.n = 21;
|
|
33132
|
+
break;
|
|
33133
|
+
case 19:
|
|
33134
|
+
_context6.p = 19;
|
|
33135
|
+
_t4 = _context6.v;
|
|
33136
|
+
if (!((_t4 === null || _t4 === void 0 ? void 0 : _t4.message) === 'DISCLAIMER_DECLINED')) {
|
|
33137
|
+
_context6.n = 20;
|
|
33138
|
+
break;
|
|
33139
|
+
}
|
|
33140
|
+
this.resetConnectingState();
|
|
33141
|
+
throw _t4;
|
|
33142
|
+
case 20:
|
|
33143
|
+
throw _t4;
|
|
33144
|
+
case 21:
|
|
33145
|
+
return _context6.a(3, 15);
|
|
33146
|
+
case 22:
|
|
33147
|
+
if (vs.disclaimersPending) {
|
|
33148
|
+
_context6.n = 23;
|
|
33149
|
+
break;
|
|
33150
|
+
}
|
|
33151
|
+
return _context6.a(3, 25);
|
|
33152
|
+
case 23:
|
|
33153
|
+
_context6.n = 24;
|
|
32954
33154
|
return new Promise(function (resolve) {
|
|
32955
33155
|
return setTimeout(resolve, 100);
|
|
32956
33156
|
});
|
|
32957
|
-
case
|
|
33157
|
+
case 24:
|
|
32958
33158
|
attempts++;
|
|
32959
|
-
|
|
33159
|
+
_context6.n = 15;
|
|
32960
33160
|
break;
|
|
32961
|
-
case
|
|
33161
|
+
case 25:
|
|
32962
33162
|
if (!serverRejected) {
|
|
32963
|
-
|
|
33163
|
+
_context6.n = 26;
|
|
32964
33164
|
break;
|
|
32965
33165
|
}
|
|
32966
33166
|
// Restore original handlers before throwing
|
|
@@ -32968,9 +33168,9 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32968
33168
|
this.sdk.onDisconnected = originalOnDisconnected;
|
|
32969
33169
|
console.log('🚫 Server rejected connection, aborting audio capture');
|
|
32970
33170
|
throw new Error('DOMAIN_NOT_WHITELISTED');
|
|
32971
|
-
case
|
|
33171
|
+
case 26:
|
|
32972
33172
|
if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
|
|
32973
|
-
|
|
33173
|
+
_context6.n = 27;
|
|
32974
33174
|
break;
|
|
32975
33175
|
}
|
|
32976
33176
|
// Restore original handlers before throwing
|
|
@@ -32978,12 +33178,12 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32978
33178
|
this.sdk.onDisconnected = originalOnDisconnected;
|
|
32979
33179
|
console.warn('⚠️ Connection lost before starting audio capture');
|
|
32980
33180
|
throw new Error('Connection lost before starting audio capture');
|
|
32981
|
-
case
|
|
33181
|
+
case 27:
|
|
32982
33182
|
// Restore original handlers (connection is valid, proceed with audio)
|
|
32983
33183
|
this.sdk.onError = originalOnError;
|
|
32984
33184
|
this.sdk.onDisconnected = originalOnDisconnected;
|
|
32985
33185
|
if (!(this.sdk.isConnected && this.sdk.voiceSDK && this.sdk.voiceSDK.websocket && this.sdk.voiceSDK.websocket.readyState === WebSocket.OPEN)) {
|
|
32986
|
-
|
|
33186
|
+
_context6.n = 38;
|
|
32987
33187
|
break;
|
|
32988
33188
|
}
|
|
32989
33189
|
console.log('✅ WebSocket ready, starting listening...');
|
|
@@ -32993,35 +33193,35 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
32993
33193
|
|
|
32994
33194
|
// CRITICAL: startListening() will request microphone permission
|
|
32995
33195
|
// iOS: Pass preliminary stream to avoid second getUserMedia (single-stream fix)
|
|
32996
|
-
|
|
33196
|
+
_context6.p = 28;
|
|
32997
33197
|
streamToUse = this._preliminaryInputStream || null;
|
|
32998
33198
|
if (streamToUse) this._preliminaryInputStream = null; // Transfer ownership to AudioRecorder
|
|
32999
|
-
|
|
33199
|
+
_context6.n = 29;
|
|
33000
33200
|
return this.sdk.startListening(streamToUse);
|
|
33001
|
-
case
|
|
33201
|
+
case 29:
|
|
33002
33202
|
if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
|
|
33003
|
-
|
|
33203
|
+
_context6.n = 34;
|
|
33004
33204
|
break;
|
|
33005
33205
|
}
|
|
33006
33206
|
if (!((_this$sdk$voiceSDK = this.sdk.voiceSDK) !== null && _this$sdk$voiceSDK !== void 0 && _this$sdk$voiceSDK.isRecording)) {
|
|
33007
|
-
|
|
33207
|
+
_context6.n = 33;
|
|
33008
33208
|
break;
|
|
33009
33209
|
}
|
|
33010
|
-
|
|
33011
|
-
|
|
33210
|
+
_context6.p = 30;
|
|
33211
|
+
_context6.n = 31;
|
|
33012
33212
|
return this.sdk.voiceSDK.stopRecording();
|
|
33013
|
-
case
|
|
33014
|
-
|
|
33213
|
+
case 31:
|
|
33214
|
+
_context6.n = 33;
|
|
33015
33215
|
break;
|
|
33016
|
-
case
|
|
33017
|
-
|
|
33018
|
-
|
|
33019
|
-
case
|
|
33216
|
+
case 32:
|
|
33217
|
+
_context6.p = 32;
|
|
33218
|
+
_t5 = _context6.v;
|
|
33219
|
+
case 33:
|
|
33020
33220
|
error = new Error('Connection lost - server may have rejected the call');
|
|
33021
33221
|
error.name = 'ServerRejected';
|
|
33022
33222
|
error.isServerRejection = true;
|
|
33023
33223
|
throw error;
|
|
33024
|
-
case
|
|
33224
|
+
case 34:
|
|
33025
33225
|
console.log('🎤 Started listening - permission granted');
|
|
33026
33226
|
|
|
33027
33227
|
// ElevenLabs pattern: NOW stop preliminary stream - real input is ready
|
|
@@ -33061,23 +33261,23 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33061
33261
|
// Start live waveform animation interval (delegated to desktop module)
|
|
33062
33262
|
this.desktop.startLiveWaveformInterval();
|
|
33063
33263
|
}
|
|
33064
|
-
|
|
33264
|
+
_context6.n = 37;
|
|
33065
33265
|
break;
|
|
33066
|
-
case
|
|
33067
|
-
|
|
33068
|
-
|
|
33069
|
-
if (!(
|
|
33070
|
-
|
|
33266
|
+
case 35:
|
|
33267
|
+
_context6.p = 35;
|
|
33268
|
+
_t6 = _context6.v;
|
|
33269
|
+
if (!(_t6.isServerRejection || _t6.name === 'ServerRejected')) {
|
|
33270
|
+
_context6.n = 36;
|
|
33071
33271
|
break;
|
|
33072
33272
|
}
|
|
33073
33273
|
// Server rejection is expected - handle it silently
|
|
33074
33274
|
// The error handler will show domain error message
|
|
33075
33275
|
this.resetConnectingState();
|
|
33076
33276
|
// Re-throw so outer catch can handle it appropriately
|
|
33077
|
-
throw
|
|
33078
|
-
case
|
|
33277
|
+
throw _t6;
|
|
33278
|
+
case 36:
|
|
33079
33279
|
// Log other errors (permission denied, etc.)
|
|
33080
|
-
console.error('❌ Failed to start listening - permission denied or error:',
|
|
33280
|
+
console.error('❌ Failed to start listening - permission denied or error:', _t6);
|
|
33081
33281
|
// Permission was denied or error occurred - reset connecting state and restore UI
|
|
33082
33282
|
this.resetConnectingState();
|
|
33083
33283
|
if (this.isMobile) {
|
|
@@ -33113,8 +33313,8 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33113
33313
|
}
|
|
33114
33314
|
}
|
|
33115
33315
|
// Re-throw error so it's handled by outer catch
|
|
33116
|
-
throw
|
|
33117
|
-
case
|
|
33316
|
+
throw _t6;
|
|
33317
|
+
case 37:
|
|
33118
33318
|
// Start timer (desktop only - mobile bar owns its own timer)
|
|
33119
33319
|
if (!this.isMobile && !this.callStartTime) {
|
|
33120
33320
|
this.callStartTime = Date.now();
|
|
@@ -33132,30 +33332,30 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33132
33332
|
_this3.callTimerInterval = setInterval(updateTimer, 1000);
|
|
33133
33333
|
}, 100);
|
|
33134
33334
|
}
|
|
33135
|
-
|
|
33335
|
+
_context6.n = 46;
|
|
33136
33336
|
break;
|
|
33137
|
-
case
|
|
33337
|
+
case 38:
|
|
33138
33338
|
if (!serverRejected) {
|
|
33139
|
-
|
|
33339
|
+
_context6.n = 39;
|
|
33140
33340
|
break;
|
|
33141
33341
|
}
|
|
33142
33342
|
console.log('🚫 Server rejected connection, aborting audio capture');
|
|
33143
33343
|
throw new Error('DOMAIN_NOT_WHITELISTED');
|
|
33144
|
-
case
|
|
33344
|
+
case 39:
|
|
33145
33345
|
if (!(!this.sdk.isConnected || !this.sdk.voiceSDK || !this.sdk.voiceSDK.isConnected || !this.sdk.voiceSDK.websocket || this.sdk.voiceSDK.websocket.readyState !== WebSocket.OPEN)) {
|
|
33146
|
-
|
|
33346
|
+
_context6.n = 40;
|
|
33147
33347
|
break;
|
|
33148
33348
|
}
|
|
33149
33349
|
console.warn('⚠️ Connection not valid, aborting audio capture');
|
|
33150
33350
|
throw new Error('Connection lost before starting audio capture');
|
|
33151
|
-
case
|
|
33351
|
+
case 40:
|
|
33152
33352
|
console.warn('⚠️ Connection not fully ready, but trying to start listening anyway...');
|
|
33153
|
-
|
|
33353
|
+
_context6.p = 41;
|
|
33154
33354
|
_streamToUse = this._preliminaryInputStream || null;
|
|
33155
33355
|
if (_streamToUse) this._preliminaryInputStream = null;
|
|
33156
|
-
|
|
33356
|
+
_context6.n = 42;
|
|
33157
33357
|
return this.sdk.startListening(_streamToUse);
|
|
33158
|
-
case
|
|
33358
|
+
case 42:
|
|
33159
33359
|
console.log('🎤 Started listening - permission granted');
|
|
33160
33360
|
|
|
33161
33361
|
// ElevenLabs pattern: NOW stop preliminary stream - real input is ready
|
|
@@ -33195,23 +33395,23 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33195
33395
|
// Start live waveform animation interval (delegated to desktop module)
|
|
33196
33396
|
this.desktop.startLiveWaveformInterval();
|
|
33197
33397
|
}
|
|
33198
|
-
|
|
33398
|
+
_context6.n = 45;
|
|
33199
33399
|
break;
|
|
33200
|
-
case
|
|
33201
|
-
|
|
33202
|
-
|
|
33203
|
-
if (!(
|
|
33204
|
-
|
|
33400
|
+
case 43:
|
|
33401
|
+
_context6.p = 43;
|
|
33402
|
+
_t7 = _context6.v;
|
|
33403
|
+
if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
|
|
33404
|
+
_context6.n = 44;
|
|
33205
33405
|
break;
|
|
33206
33406
|
}
|
|
33207
33407
|
// Server rejection is expected - handle it silently
|
|
33208
33408
|
// The error handler will show domain error message
|
|
33209
33409
|
this.resetConnectingState();
|
|
33210
33410
|
// Re-throw so outer catch can handle it appropriately
|
|
33211
|
-
throw
|
|
33212
|
-
case
|
|
33411
|
+
throw _t7;
|
|
33412
|
+
case 44:
|
|
33213
33413
|
// Log other errors (permission denied, etc.)
|
|
33214
|
-
console.error('❌ Failed to start listening - permission denied or error:',
|
|
33414
|
+
console.error('❌ Failed to start listening - permission denied or error:', _t7);
|
|
33215
33415
|
// Permission was denied or error occurred - reset connecting state and restore UI
|
|
33216
33416
|
this.resetConnectingState();
|
|
33217
33417
|
if (this.isMobile) {
|
|
@@ -33247,8 +33447,8 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33247
33447
|
}
|
|
33248
33448
|
}
|
|
33249
33449
|
// Re-throw error so it's handled by outer catch
|
|
33250
|
-
throw
|
|
33251
|
-
case
|
|
33450
|
+
throw _t7;
|
|
33451
|
+
case 45:
|
|
33252
33452
|
// Start timer (desktop only - mobile bar owns its own timer)
|
|
33253
33453
|
if (!this.isMobile && !this.callStartTime) {
|
|
33254
33454
|
this.callStartTime = Date.now();
|
|
@@ -33266,16 +33466,16 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33266
33466
|
_this3.callTimerInterval = setInterval(_updateTimer, 1000);
|
|
33267
33467
|
}, 100);
|
|
33268
33468
|
}
|
|
33269
|
-
case
|
|
33469
|
+
case 46:
|
|
33270
33470
|
console.log('✅ Voice call started successfully');
|
|
33271
|
-
|
|
33471
|
+
_context6.n = 52;
|
|
33272
33472
|
break;
|
|
33273
|
-
case
|
|
33274
|
-
|
|
33275
|
-
|
|
33473
|
+
case 47:
|
|
33474
|
+
_context6.p = 47;
|
|
33475
|
+
_t8 = _context6.v;
|
|
33276
33476
|
// Handle server rejection gracefully (don't log as error)
|
|
33277
|
-
if (!(
|
|
33278
|
-
console.error('❌ Error starting voice call:',
|
|
33477
|
+
if (!(_t8.isServerRejection || _t8.name === 'ServerRejected')) {
|
|
33478
|
+
console.error('❌ Error starting voice call:', _t8);
|
|
33279
33479
|
}
|
|
33280
33480
|
|
|
33281
33481
|
// ElevenLabs pattern: Stop preliminary stream on any error path
|
|
@@ -33305,50 +33505,50 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33305
33505
|
}
|
|
33306
33506
|
|
|
33307
33507
|
// Handle specific error types with appropriate modals
|
|
33308
|
-
if (!(
|
|
33309
|
-
|
|
33508
|
+
if (!(_t8.name === 'NotAllowedError' || _t8.name === 'PermissionDeniedError')) {
|
|
33509
|
+
_context6.n = 48;
|
|
33310
33510
|
break;
|
|
33311
33511
|
}
|
|
33312
33512
|
// Permission denied - show blocked modal
|
|
33313
|
-
_deviceInfo = (0,
|
|
33314
|
-
(0,
|
|
33513
|
+
_deviceInfo = (0,_shared_MicPermissionUtils_js__WEBPACK_IMPORTED_MODULE_2__.getDeviceInfo)();
|
|
33514
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showBlockedModal)(function () {
|
|
33315
33515
|
// Modal closed
|
|
33316
33516
|
_this3.resetUIState();
|
|
33317
33517
|
}, function () {
|
|
33318
33518
|
// User clicked refresh
|
|
33319
33519
|
window.location.reload();
|
|
33320
33520
|
});
|
|
33321
|
-
|
|
33521
|
+
_context6.n = 52;
|
|
33322
33522
|
break;
|
|
33323
|
-
case
|
|
33324
|
-
if (!(
|
|
33325
|
-
|
|
33523
|
+
case 48:
|
|
33524
|
+
if (!(_t8.name === 'NotFoundError' || _t8.name === 'DevicesNotFoundError')) {
|
|
33525
|
+
_context6.n = 49;
|
|
33326
33526
|
break;
|
|
33327
33527
|
}
|
|
33328
33528
|
// No microphone found - show no mic modal
|
|
33329
|
-
(0,
|
|
33529
|
+
(0,_shared_MicPermissionModals_js__WEBPACK_IMPORTED_MODULE_4__.showNoMicrophoneModal)(function () {
|
|
33330
33530
|
_this3.resetUIState();
|
|
33331
33531
|
});
|
|
33332
|
-
|
|
33532
|
+
_context6.n = 52;
|
|
33333
33533
|
break;
|
|
33334
|
-
case
|
|
33335
|
-
if (!(
|
|
33336
|
-
|
|
33534
|
+
case 49:
|
|
33535
|
+
if (!(_t8 && (_t8.message === 'DOMAIN_NOT_WHITELISTED' || _t8.message && _t8.message.includes('Domain not whitelisted')))) {
|
|
33536
|
+
_context6.n = 51;
|
|
33337
33537
|
break;
|
|
33338
33538
|
}
|
|
33339
|
-
|
|
33539
|
+
_context6.n = 50;
|
|
33340
33540
|
return this.endCallOnServerRejection();
|
|
33341
|
-
case
|
|
33342
|
-
|
|
33541
|
+
case 50:
|
|
33542
|
+
_context6.n = 52;
|
|
33343
33543
|
break;
|
|
33344
|
-
case
|
|
33544
|
+
case 51:
|
|
33345
33545
|
// Other errors - show in transcript
|
|
33346
|
-
this.showError(
|
|
33546
|
+
this.showError(_t8.message || _t8);
|
|
33347
33547
|
this.resetUIState();
|
|
33348
|
-
case
|
|
33349
|
-
return
|
|
33548
|
+
case 52:
|
|
33549
|
+
return _context6.a(2);
|
|
33350
33550
|
}
|
|
33351
|
-
},
|
|
33551
|
+
}, _callee6, this, [[41, 43], [30, 32], [28, 35], [17, 19], [9, 11], [1, 4], [0, 47]]);
|
|
33352
33552
|
}));
|
|
33353
33553
|
function proceedWithVoiceCall() {
|
|
33354
33554
|
return _proceedWithVoiceCall.apply(this, arguments);
|
|
@@ -33359,7 +33559,6 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33359
33559
|
* Stop preliminary mic stream (ElevenLabs pattern).
|
|
33360
33560
|
* Must be called after startListening succeeds, or on any error path.
|
|
33361
33561
|
*/
|
|
33362
|
-
)
|
|
33363
33562
|
}, {
|
|
33364
33563
|
key: "_stopPreliminaryInputStream",
|
|
33365
33564
|
value: function _stopPreliminaryInputStream() {
|
|
@@ -33414,10 +33613,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33414
33613
|
}, {
|
|
33415
33614
|
key: "endCallOnServerRejection",
|
|
33416
33615
|
value: (function () {
|
|
33417
|
-
var _endCallOnServerRejection = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
33418
|
-
var voiceInterfaceEl, landingScreen, _this$sdk$voiceSDK2, _this$sdk$voiceSDK3, audioRecorder, isRecording, _this$sdk$voiceSDK4, activeState, idleState, panel, fallbackPanel, floatingButton, fallbackButton, mobileFabEnd, errorMsg,
|
|
33419
|
-
return _regenerator().w(function (
|
|
33420
|
-
while (1) switch (
|
|
33616
|
+
var _endCallOnServerRejection = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
33617
|
+
var voiceInterfaceEl, landingScreen, _this$sdk$voiceSDK2, _this$sdk$voiceSDK3, audioRecorder, isRecording, _this$sdk$voiceSDK4, activeState, idleState, panel, fallbackPanel, floatingButton, fallbackButton, mobileFabEnd, errorMsg, _t9, _t0, _t1, _t10, _t11;
|
|
33618
|
+
return _regenerator().w(function (_context7) {
|
|
33619
|
+
while (1) switch (_context7.p = _context7.n) {
|
|
33421
33620
|
case 0:
|
|
33422
33621
|
console.log('🚫 Server rejected call - ending call and stopping audio capture/VAD...');
|
|
33423
33622
|
console.log('🚫 Calling endCallOnServerRejection() - will show domain error message');
|
|
@@ -33444,94 +33643,94 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33444
33643
|
|
|
33445
33644
|
// CRITICAL: Stop audio capture/VAD immediately
|
|
33446
33645
|
if (!this.sdk) {
|
|
33447
|
-
|
|
33646
|
+
_context7.n = 22;
|
|
33448
33647
|
break;
|
|
33449
33648
|
}
|
|
33450
|
-
|
|
33649
|
+
_context7.p = 1;
|
|
33451
33650
|
// CRITICAL: Stop VAD and audio capture immediately
|
|
33452
33651
|
// Check if AudioRecorder exists and is recording (even if flags aren't set yet)
|
|
33453
33652
|
audioRecorder = (_this$sdk$voiceSDK2 = this.sdk.voiceSDK) === null || _this$sdk$voiceSDK2 === void 0 ? void 0 : _this$sdk$voiceSDK2.audioRecorder;
|
|
33454
33653
|
isRecording = this.sdk.isListening || ((_this$sdk$voiceSDK3 = this.sdk.voiceSDK) === null || _this$sdk$voiceSDK3 === void 0 ? void 0 : _this$sdk$voiceSDK3.isRecording) || audioRecorder && audioRecorder.isRecording || audioRecorder && audioRecorder.audioWorkletNode !== null;
|
|
33455
33654
|
if (!(isRecording || audioRecorder)) {
|
|
33456
|
-
|
|
33655
|
+
_context7.n = 19;
|
|
33457
33656
|
break;
|
|
33458
33657
|
}
|
|
33459
33658
|
console.log('🛑 Stopping audio capture/VAD...');
|
|
33460
33659
|
|
|
33461
33660
|
// First, send stop message to AudioWorklet to stop VAD processing
|
|
33462
33661
|
if (!(audioRecorder !== null && audioRecorder !== void 0 && audioRecorder.audioWorkletNode)) {
|
|
33463
|
-
|
|
33662
|
+
_context7.n = 5;
|
|
33464
33663
|
break;
|
|
33465
33664
|
}
|
|
33466
33665
|
console.log('🛑 Sending stop message to AudioWorklet to stop VAD...');
|
|
33467
|
-
|
|
33666
|
+
_context7.p = 2;
|
|
33468
33667
|
audioRecorder.audioWorkletNode.port.postMessage({
|
|
33469
33668
|
type: 'stop'
|
|
33470
33669
|
});
|
|
33471
|
-
|
|
33670
|
+
_context7.n = 3;
|
|
33472
33671
|
return new Promise(function (resolve) {
|
|
33473
33672
|
return setTimeout(resolve, 150);
|
|
33474
33673
|
});
|
|
33475
33674
|
case 3:
|
|
33476
|
-
|
|
33675
|
+
_context7.n = 5;
|
|
33477
33676
|
break;
|
|
33478
33677
|
case 4:
|
|
33479
|
-
|
|
33480
|
-
|
|
33481
|
-
console.warn('Error sending stop message to AudioWorklet:',
|
|
33678
|
+
_context7.p = 4;
|
|
33679
|
+
_t9 = _context7.v;
|
|
33680
|
+
console.warn('Error sending stop message to AudioWorklet:', _t9);
|
|
33482
33681
|
case 5:
|
|
33483
33682
|
if (!(this.sdk.voiceSDK && typeof this.sdk.voiceSDK.stopRecording === 'function')) {
|
|
33484
|
-
|
|
33683
|
+
_context7.n = 10;
|
|
33485
33684
|
break;
|
|
33486
33685
|
}
|
|
33487
|
-
|
|
33488
|
-
|
|
33686
|
+
_context7.p = 6;
|
|
33687
|
+
_context7.n = 7;
|
|
33489
33688
|
return this.sdk.voiceSDK.stopRecording();
|
|
33490
33689
|
case 7:
|
|
33491
33690
|
console.log('✅ stopRecording() completed');
|
|
33492
|
-
|
|
33691
|
+
_context7.n = 9;
|
|
33493
33692
|
break;
|
|
33494
33693
|
case 8:
|
|
33495
|
-
|
|
33496
|
-
|
|
33497
|
-
console.warn('Error calling stopRecording:',
|
|
33694
|
+
_context7.p = 8;
|
|
33695
|
+
_t0 = _context7.v;
|
|
33696
|
+
console.warn('Error calling stopRecording:', _t0);
|
|
33498
33697
|
case 9:
|
|
33499
|
-
|
|
33698
|
+
_context7.n = 14;
|
|
33500
33699
|
break;
|
|
33501
33700
|
case 10:
|
|
33502
33701
|
if (!this.sdk.stopListening) {
|
|
33503
|
-
|
|
33702
|
+
_context7.n = 14;
|
|
33504
33703
|
break;
|
|
33505
33704
|
}
|
|
33506
|
-
|
|
33705
|
+
_context7.p = 11;
|
|
33507
33706
|
this.sdk.stopListening();
|
|
33508
|
-
|
|
33707
|
+
_context7.n = 12;
|
|
33509
33708
|
return new Promise(function (resolve) {
|
|
33510
33709
|
return setTimeout(resolve, 200);
|
|
33511
33710
|
});
|
|
33512
33711
|
case 12:
|
|
33513
|
-
|
|
33712
|
+
_context7.n = 14;
|
|
33514
33713
|
break;
|
|
33515
33714
|
case 13:
|
|
33516
|
-
|
|
33517
|
-
|
|
33518
|
-
console.warn('Error calling stopListening:',
|
|
33715
|
+
_context7.p = 13;
|
|
33716
|
+
_t1 = _context7.v;
|
|
33717
|
+
console.warn('Error calling stopListening:', _t1);
|
|
33519
33718
|
case 14:
|
|
33520
33719
|
if (!(audioRecorder && typeof audioRecorder.stop === 'function')) {
|
|
33521
|
-
|
|
33720
|
+
_context7.n = 18;
|
|
33522
33721
|
break;
|
|
33523
33722
|
}
|
|
33524
|
-
|
|
33525
|
-
|
|
33723
|
+
_context7.p = 15;
|
|
33724
|
+
_context7.n = 16;
|
|
33526
33725
|
return audioRecorder.stop();
|
|
33527
33726
|
case 16:
|
|
33528
33727
|
console.log('✅ AudioRecorder.stop() completed');
|
|
33529
|
-
|
|
33728
|
+
_context7.n = 18;
|
|
33530
33729
|
break;
|
|
33531
33730
|
case 17:
|
|
33532
|
-
|
|
33533
|
-
|
|
33534
|
-
console.warn('Error calling AudioRecorder.stop():',
|
|
33731
|
+
_context7.p = 17;
|
|
33732
|
+
_t10 = _context7.v;
|
|
33733
|
+
console.warn('Error calling AudioRecorder.stop():', _t10);
|
|
33535
33734
|
case 18:
|
|
33536
33735
|
console.log('✅ Audio capture/VAD stopped');
|
|
33537
33736
|
case 19:
|
|
@@ -33559,12 +33758,12 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33559
33758
|
|
|
33560
33759
|
// Hangup the call
|
|
33561
33760
|
this.sdk.hangup();
|
|
33562
|
-
|
|
33761
|
+
_context7.n = 21;
|
|
33563
33762
|
break;
|
|
33564
33763
|
case 20:
|
|
33565
|
-
|
|
33566
|
-
|
|
33567
|
-
console.warn('Error stopping listening on server rejection:',
|
|
33764
|
+
_context7.p = 20;
|
|
33765
|
+
_t11 = _context7.v;
|
|
33766
|
+
console.warn('Error stopping listening on server rejection:', _t11);
|
|
33568
33767
|
// Force stop media streams even if stopListening fails
|
|
33569
33768
|
try {
|
|
33570
33769
|
if ((_this$sdk$voiceSDK4 = this.sdk.voiceSDK) !== null && _this$sdk$voiceSDK4 !== void 0 && (_this$sdk$voiceSDK4 = _this$sdk$voiceSDK4.audioRecorder) !== null && _this$sdk$voiceSDK4 !== void 0 && _this$sdk$voiceSDK4.mediaStream) {
|
|
@@ -33666,9 +33865,9 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
33666
33865
|
}
|
|
33667
33866
|
}
|
|
33668
33867
|
case 23:
|
|
33669
|
-
return
|
|
33868
|
+
return _context7.a(2);
|
|
33670
33869
|
}
|
|
33671
|
-
},
|
|
33870
|
+
}, _callee7, this, [[15, 17], [11, 13], [6, 8], [2, 4], [1, 20]]);
|
|
33672
33871
|
}));
|
|
33673
33872
|
function endCallOnServerRejection() {
|
|
33674
33873
|
return _endCallOnServerRejection.apply(this, arguments);
|
|
@@ -34262,6 +34461,45 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
34262
34461
|
return this.mobile.createMobileMinimizedBar();
|
|
34263
34462
|
}
|
|
34264
34463
|
|
|
34464
|
+
/**
|
|
34465
|
+
* Mobile: ensure minimized bar exists with copy for the native getUserMedia permission dialog.
|
|
34466
|
+
*/
|
|
34467
|
+
}, {
|
|
34468
|
+
key: "showMobileCallBarAwaitingBrowserMic",
|
|
34469
|
+
value: function showMobileCallBarAwaitingBrowserMic() {
|
|
34470
|
+
if (!document.getElementById('mobile-voice-call-bar-container')) {
|
|
34471
|
+
this.createMobileMinimizedBar();
|
|
34472
|
+
}
|
|
34473
|
+
var root = document.getElementById('mobile-voice-call-bar-container');
|
|
34474
|
+
if (!root) return;
|
|
34475
|
+
var line = this.t('awaitingBrowserMic');
|
|
34476
|
+
var detail = this.t('awaitingBrowserMicDetail');
|
|
34477
|
+
var status = root.querySelector('#mobileStatusText');
|
|
34478
|
+
var headerStatus = root.querySelector('#mobileHeaderStatusText');
|
|
34479
|
+
if (status) status.textContent = line;
|
|
34480
|
+
if (headerStatus) headerStatus.textContent = line;
|
|
34481
|
+
var tx = root.querySelector('#mobileTranscriptText');
|
|
34482
|
+
if (tx) tx.textContent = detail;
|
|
34483
|
+
}
|
|
34484
|
+
|
|
34485
|
+
/**
|
|
34486
|
+
* Mobile: after mic permission granted, show standard "connecting" copy until audio starts.
|
|
34487
|
+
*/
|
|
34488
|
+
}, {
|
|
34489
|
+
key: "applyMobileBarConnectingCopy",
|
|
34490
|
+
value: function applyMobileBarConnectingCopy() {
|
|
34491
|
+
var root = document.getElementById('mobile-voice-call-bar-container');
|
|
34492
|
+
if (!root) return;
|
|
34493
|
+
var line = this.t('connecting');
|
|
34494
|
+
var detail = this.t('connectingSubtitle');
|
|
34495
|
+
var status = root.querySelector('#mobileStatusText');
|
|
34496
|
+
var headerStatus = root.querySelector('#mobileHeaderStatusText');
|
|
34497
|
+
if (status) status.textContent = line;
|
|
34498
|
+
if (headerStatus) headerStatus.textContent = line;
|
|
34499
|
+
var tx = root.querySelector('#mobileTranscriptText');
|
|
34500
|
+
if (tx) tx.textContent = detail;
|
|
34501
|
+
}
|
|
34502
|
+
|
|
34265
34503
|
/**
|
|
34266
34504
|
* Remove mobile minimized bar
|
|
34267
34505
|
* Delegates to mobile module
|
|
@@ -35495,7 +35733,7 @@ var Handlers = /*#__PURE__*/function () {
|
|
|
35495
35733
|
};
|
|
35496
35734
|
};
|
|
35497
35735
|
var onTouchEnd = function onTouchEnd(e) {
|
|
35498
|
-
var _mobileTextInputEl$va;
|
|
35736
|
+
var _overlay$classList, _mobileTextInputEl$va;
|
|
35499
35737
|
var container = document.getElementById('mobile-voice-call-bar-container');
|
|
35500
35738
|
if (!container || !touchOrigin || !e.changedTouches.length) {
|
|
35501
35739
|
touchOrigin = null;
|
|
@@ -35516,7 +35754,7 @@ var Handlers = /*#__PURE__*/function () {
|
|
|
35516
35754
|
var mobileSendBtnEl = container.querySelector('#mobileSendBtn');
|
|
35517
35755
|
var mobileTextInputEl = container.querySelector('#mobileTextInput');
|
|
35518
35756
|
var overlay = container.querySelector('#mobileTranscriptOverlay');
|
|
35519
|
-
var isOverlayVisible = overlay &&
|
|
35757
|
+
var isOverlayVisible = !!(overlay !== null && overlay !== void 0 && (_overlay$classList = overlay.classList) !== null && _overlay$classList !== void 0 && _overlay$classList.contains('mobile-transcript-overlay--open'));
|
|
35520
35758
|
if (hitTest(x, y, endBtn)) {
|
|
35521
35759
|
e.preventDefault();
|
|
35522
35760
|
e.stopPropagation();
|
|
@@ -35710,20 +35948,23 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35710
35948
|
existingBar.remove();
|
|
35711
35949
|
}
|
|
35712
35950
|
|
|
35713
|
-
// Inject mobile CSS
|
|
35714
|
-
|
|
35715
|
-
|
|
35716
|
-
|
|
35717
|
-
|
|
35718
|
-
document.head.appendChild(
|
|
35951
|
+
// Inject / refresh mobile CSS in document head (must match current voice config each call)
|
|
35952
|
+
var mobileStyleEl = document.getElementById('mobile-voice-call-bar-styles');
|
|
35953
|
+
if (!mobileStyleEl) {
|
|
35954
|
+
mobileStyleEl = document.createElement('style');
|
|
35955
|
+
mobileStyleEl.id = 'mobile-voice-call-bar-styles';
|
|
35956
|
+
document.head.appendChild(mobileStyleEl);
|
|
35719
35957
|
}
|
|
35958
|
+
mobileStyleEl.textContent = this.voiceInterface.styles.generateMobileCSS();
|
|
35720
35959
|
|
|
35721
35960
|
// Create container div
|
|
35722
35961
|
var container = document.createElement('div');
|
|
35723
35962
|
container.id = 'mobile-voice-call-bar-container';
|
|
35963
|
+
var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
|
|
35964
|
+
container.setAttribute('dir', textDir);
|
|
35724
35965
|
container.innerHTML = "\n <!-- Duration Badge (hidden until first audio) -->\n <div class=\"mobile-duration-badge mobile-duration-badge--hidden\" id=\"mobileDurationBadge\">\n <div class=\"mobile-duration-dot\"></div>\n <span id=\"mobileDurationText\">00:00</span>\n </div>\n \n <!-- Main Bar -->\n <div class=\"mobile-voice-bar\">\n <!-- Top Row: Status, Waveform/Spinner, Controls -->\n <div class=\"mobile-top-row\">\n <!-- Status Indicator -->\n <div class=\"mobile-status-indicator\">\n <div class=\"mobile-status-dot\" id=\"mobileStatusDot\"></div>\n <span class=\"mobile-status-text\" id=\"mobileStatusText\">".concat(this.t('listening'), "</span>\n </div>\n \n <!-- Centered: Spinner (loading) or Waveform (after first audio) -->\n <div class=\"mobile-waveform-center\" id=\"mobileWaveform\">\n <div class=\"mobile-waveform-spinner\" id=\"mobileWaveformSpinner\" aria-hidden=\"false\">\n <div class=\"mobile-waveform-spinner-inner\"></div>\n </div>\n <div class=\"mobile-waveform-bars mobile-waveform-bars--hidden\" id=\"mobileWaveformBars\">\n ").concat(Array(8).fill(0).map(function (_, i) {
|
|
35725
35966
|
return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
|
|
35726
|
-
}).join(''), "\n </div>\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n\n <!-- Fly-to-cart target: always visible for animation (positioned where cart icon appears) -->\n <div id=\"ttpFlyToCartTarget\" class=\"ttp-fly-target\" aria-hidden=\"true\"></div>\n\n <!-- Cart Row - shown when items are in cart -->\n <div class=\"mobile-cart-row\" id=\"mobileCartRow\" style=\"display: none;\">\n <div class=\"mobile-cart-row__content\">\n <span class=\"mobile-cart-row__icon\" data-ttp-fly-target>\uD83D\uDED2</span>\n <span class=\"mobile-cart-row__text\" id=\"mobileCartText\">0 items \xB7 \u20AA0.00</span>\n </div>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\"
|
|
35967
|
+
}).join(''), "\n </div>\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\" dir=\"").concat(textDir, "\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n\n <!-- Fly-to-cart target: always visible for animation (positioned where cart icon appears) -->\n <div id=\"ttpFlyToCartTarget\" class=\"ttp-fly-target\" aria-hidden=\"true\"></div>\n\n <!-- Cart Row - shown when items are in cart -->\n <div class=\"mobile-cart-row\" id=\"mobileCartRow\" style=\"display: none;\">\n <div class=\"mobile-cart-row__content\">\n <span class=\"mobile-cart-row__icon\" data-ttp-fly-target>\uD83D\uDED2</span>\n <span class=\"mobile-cart-row__text\" id=\"mobileCartText\">0 items \xB7 \u20AA0.00</span>\n </div>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">").concat(this.t('listening'), "</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n dir=\"").concat(textDir, "\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F ").concat(this.t('voiceActive') || 'Voice is still active', " \u2022 ").concat(this.t('typeOrSpeak') || 'Type or speak', "</p>\n </div>\n </div>\n </div>\n ");
|
|
35727
35968
|
|
|
35728
35969
|
// Append to body
|
|
35729
35970
|
document.body.appendChild(container);
|
|
@@ -35857,7 +36098,7 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35857
36098
|
var container = document.getElementById('mobile-voice-call-bar-container');
|
|
35858
36099
|
var overlay = container === null || container === void 0 ? void 0 : container.querySelector('#mobileTranscriptOverlay');
|
|
35859
36100
|
if (overlay) {
|
|
35860
|
-
overlay.
|
|
36101
|
+
overlay.classList.add('mobile-transcript-overlay--open');
|
|
35861
36102
|
this.isTranscriptExpanded = true;
|
|
35862
36103
|
|
|
35863
36104
|
// Focus input and sync send button state (container-scoped for Shopify)
|
|
@@ -35891,7 +36132,7 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35891
36132
|
var container = document.getElementById('mobile-voice-call-bar-container');
|
|
35892
36133
|
var overlay = container === null || container === void 0 ? void 0 : container.querySelector('#mobileTranscriptOverlay');
|
|
35893
36134
|
if (overlay) {
|
|
35894
|
-
overlay.
|
|
36135
|
+
overlay.classList.remove('mobile-transcript-overlay--open');
|
|
35895
36136
|
this.isTranscriptExpanded = false;
|
|
35896
36137
|
}
|
|
35897
36138
|
}
|
|
@@ -35912,6 +36153,8 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35912
36153
|
var customStatusText = this.config.statusText;
|
|
35913
36154
|
var displayText = '';
|
|
35914
36155
|
var dotColor = '#6b7280';
|
|
36156
|
+
var brandPrimary = this.config.primaryBtnGradient1 || this.config.startCallButtonColor || '#3b82f6';
|
|
36157
|
+
var brandSecondary = this.config.primaryBtnGradient2 || this.config.avatarGradient2 || brandPrimary;
|
|
35915
36158
|
if (customStatusText) {
|
|
35916
36159
|
// Use custom status text for all states
|
|
35917
36160
|
displayText = customStatusText;
|
|
@@ -35920,13 +36163,13 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35920
36163
|
// Use dynamic status based on state
|
|
35921
36164
|
if (status === 'connecting') {
|
|
35922
36165
|
displayText = this.t('connecting') || 'Connecting...';
|
|
35923
|
-
dotColor =
|
|
36166
|
+
dotColor = brandPrimary;
|
|
35924
36167
|
} else if (status === 'listening' || status === 'recording') {
|
|
35925
36168
|
displayText = this.t('listening') || 'Listening...';
|
|
35926
36169
|
dotColor = '#22c55e';
|
|
35927
36170
|
} else if (status === 'speaking') {
|
|
35928
36171
|
displayText = this.t('speaking') || 'Speaking...';
|
|
35929
|
-
dotColor =
|
|
36172
|
+
dotColor = brandSecondary;
|
|
35930
36173
|
} else {
|
|
35931
36174
|
displayText = this.t('paused') || 'Paused';
|
|
35932
36175
|
dotColor = '#facc15';
|
|
@@ -35958,6 +36201,7 @@ var Mobile = /*#__PURE__*/function () {
|
|
|
35958
36201
|
// Render message
|
|
35959
36202
|
var messageEl = document.createElement('div');
|
|
35960
36203
|
messageEl.className = "mobile-message-bubble ".concat(type);
|
|
36204
|
+
messageEl.setAttribute('dir', this.config.direction === 'rtl' ? 'rtl' : 'ltr');
|
|
35961
36205
|
messageEl.textContent = text;
|
|
35962
36206
|
messagesContainer.appendChild(messageEl);
|
|
35963
36207
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
@@ -36077,8 +36321,9 @@ var Styles = /*#__PURE__*/function () {
|
|
|
36077
36321
|
var agentRoleColor = c.agentRoleColor || 'rgba(255,255,255,0.35)';
|
|
36078
36322
|
var headlineColor = c.headlineColor || '#ffffff';
|
|
36079
36323
|
var sublineColor = c.sublineColor || 'rgba(255,255,255,0.45)';
|
|
36080
|
-
var primaryGrad1 = c.primaryBtnGradient1 || '#6d56f5';
|
|
36081
|
-
var primaryGrad2 = c.primaryBtnGradient2 || '#9d8df8';
|
|
36324
|
+
var primaryGrad1 = c.primaryBtnGradient1 || c.startCallButtonColor || '#6d56f5';
|
|
36325
|
+
var primaryGrad2 = c.primaryBtnGradient2 || c.startCallButtonColor || '#9d8df8';
|
|
36326
|
+
var talkToPcFooterLink = c._talkToPcLinkColor || primaryGrad1;
|
|
36082
36327
|
var primaryTextColor = c.startCallButtonTextColor || '#fff';
|
|
36083
36328
|
var secondaryBg = c.secondaryBtnBg || 'rgba(255,255,255,0.05)';
|
|
36084
36329
|
var secondaryBorder = c.secondaryBtnBorder || 'rgba(255,255,255,0.09)';
|
|
@@ -36086,7 +36331,8 @@ var Styles = /*#__PURE__*/function () {
|
|
|
36086
36331
|
var panelBg = c.panelBackgroundColor || '#16161e';
|
|
36087
36332
|
var endCallColor = c.endCallButtonColor || '#ef4444';
|
|
36088
36333
|
var sendBtnColor = c.sendButtonColor || primaryGrad1;
|
|
36089
|
-
return "\n /* Voice Interface - Dark Theme Desktop */\n .voice-interface {\n display: none".concat(important, ";\n flex: 1").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: stretch").concat(important, ";\n justify-content: flex-start").concat(important, ";\n padding: 0").concat(important, ";\n background: ").concat(panelBg, ";\n overflow: hidden").concat(important, ";\n min-height: 0").concat(important, ";\n height: 100%").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .voice-interface.active { display: flex").concat(important, "; }\n\n .voice-interface.active:has(#voiceIdleState:not([style*=\"display: none\"]):not([style*=\"display:none\"])) {\n background: transparent").concat(important, ";\n }\n\n /* Footer stays transparent so parent panel gradient (incl. Powered by) shows through on idle */\n .voice-interface.active ~ .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n .voice-interface.active ~ .ttp-footer span { color: rgba(255,255,255,0.35)").concat(important, "; }\n .voice-interface.active ~ .ttp-footer a { color: #a78bfa").concat(important, "; }\n\n #voiceIdleState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n #voiceIdleState[style*=\"display: none\"],\n #voiceIdleState[style*=\"display:none\"] {\n display: none !important;\n }\n\n #voiceActiveState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n flex: 1").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n #voiceActiveState[style*=\"display: none\"],\n #voiceActiveState[style*=\"display:none\"] {\n display: none !important;\n }\n\n /* \u2500\u2500 IDLE HERO \u2014 transparent; gradient is on #voiceIdleState so hero + body share one surface \u2500\u2500 */\n .ttp-hero {\n position: relative").concat(important, ";\n padding: 24px 22px 22px").concat(important, ";\n background: transparent").concat(important, ";\n border-bottom: none").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-hero::after {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: -40px").concat(important, "; right: -40px").concat(important, ";\n width: 140px").concat(important, "; height: 140px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: radial-gradient(circle, ").concat(primaryGrad1, "2e 0%, transparent 70%);\n pointer-events: none").concat(important, ";\n }\n .ttp-header {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n position: relative").concat(important, ";\n z-index: 1").concat(important, ";\n }\n .ttp-agent { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .ttp-avatar-wrap { position: relative").concat(important, "; }\n .ttp-avatar {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: #fff").concat(important, ";\n }\n .ttp-online-dot {\n position: absolute").concat(important, "; bottom: 0").concat(important, "; right: 0").concat(important, ";\n width: 10px").concat(important, "; height: 10px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(onlineDotColor, "; border: 2px solid ").concat(heroGrad2, ";\n }\n .ttp-agent-name { font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(agentNameColor, "; }\n .ttp-agent-role { font-size: 10px").concat(important, "; color: ").concat(agentRoleColor, "; margin-top: 1px").concat(important, "; }\n .ttp-close-btn {\n width: 26px").concat(important, "; height: 26px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.07)").concat(important, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n transition: background 0.2s").concat(important, ";\n }\n .ttp-close-btn:hover { background: rgba(255,255,255,0.14)").concat(important, "; }\n .ttp-headline {\n font-size: 22px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(headlineColor, ";\n line-height: 1.2").concat(important, "; margin-bottom: 6px").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n .ttp-subline {\n font-size: 13px").concat(important, "; color: ").concat(sublineColor, ";\n line-height: 1.5").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n\n /* \u2500\u2500 DOMAIN ERROR CARD \u2500\u2500 */\n .ttp-domain-error-card {\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 12px").concat(important, ";\n padding: 14px 16px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(239,68,68,0.08)").concat(important, ";\n border: 1px solid rgba(239,68,68,0.18)").concat(important, ";\n }\n .ttp-domain-error-icon {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n }\n .ttp-domain-error-text {\n font-size: 12px").concat(important, ";\n line-height: 1.55").concat(important, ";\n color: rgba(252,165,165,0.85)").concat(important, ";\n }\n .ttp-domain-error-text strong {\n color: #fca5a5").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* \u2500\u2500 IDLE BODY \u2500\u2500 */\n .ttp-body {\n padding: 10px 18px 14px").concat(important, ";\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 6px").concat(important, ";\n }\n .ttp-btn-primary {\n width: 100%").concat(important, "; padding: 11px").concat(important, "; border-radius: 12px").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n border: none").concat(important, "; cursor: pointer").concat(important, ";\n font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(primaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n box-shadow: 0 4px 18px ").concat(primaryGrad1, "59;\n transition: opacity 0.2s, transform 0.15s").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .ttp-btn-primary:hover { opacity: 0.9").concat(important, "; transform: translateY(-1px)").concat(important, "; }\n .ttp-btn-primary:disabled { cursor: not-allowed").concat(important, "; opacity: 0.6").concat(important, "; }\n .ttp-btn-secondary {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: ").concat(secondaryBg, ";\n border: 1px solid ").concat(secondaryBorder, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; color: ").concat(secondaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n }\n .ttp-btn-secondary:hover { background: ").concat(secondaryBg, "; }\n\n /* WhatsApp button */\n .ttp-btn-wa {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: rgba(37,211,102,0.08)").concat(important, ";\n border: 1px solid rgba(37,211,102,0.2)").concat(important, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: #4ade80").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n text-decoration: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .ttp-btn-wa:hover { background: rgba(37,211,102,0.14)").concat(important, "; }\n\n /* Connecting Spinner (reused from old design) */\n .connecting-spinner {\n display: inline-block").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n border: 2px solid rgba(255,255,255,0.3)").concat(important, ";\n border-top-color: #fff").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: ttp-spin 1s linear infinite").concat(important, ";\n margin-right: 8px").concat(important, ";\n vertical-align: middle").concat(important, ";\n }\n @keyframes ttp-spin { to { transform: rotate(360deg); } }\n\n /* \u2500\u2500 ACTIVE CALL \u2500\u2500 */\n .ttp-call-hero {\n background: linear-gradient(160deg, ").concat(heroGrad1, " 0%, ").concat(heroGrad2, " 100%);\n padding: 22px 20px 18px").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .ttp-call-topbar {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 18px").concat(important, ";\n }\n .ttp-rec { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 7px").concat(important, "; }\n .ttp-rec-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, "; background: #f87171").concat(important, ";\n animation: ttp-pulse 1s ease-in-out infinite").concat(important, ";\n }\n ").concat(this.config.useShadowDOM === false ? "\n /* Regular DOM (e.g. Shopify): theme rules often strip span/div sizing \u2014 recording dot + pulse */\n #ttp-widget-container .ttp-call-topbar .ttp-rec,\n #text-chat-panel .ttp-call-topbar .ttp-rec {\n display: flex !important;\n align-items: center !important;\n gap: 7px !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-rec-dot,\n #ttp-widget-container .compact-timer .ttp-rec-dot,\n #text-chat-panel .ttp-rec-dot,\n #text-chat-panel .compact-timer .ttp-rec-dot {\n display: block !important;\n flex-shrink: 0 !important;\n box-sizing: content-box !important;\n width: 7px !important;\n height: 7px !important;\n min-width: 7px !important;\n min-height: 7px !important;\n max-width: none !important;\n max-height: none !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n border-radius: 50% !important;\n background: #f87171 !important;\n background-color: #f87171 !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 1s ease-in-out infinite !important;\n animation: ttp-pulse 1s ease-in-out infinite !important;\n }\n #ttp-widget-container .ttp-transcript-hdr .ttp-dot,\n #text-chat-panel .ttp-transcript-hdr .ttp-dot {\n display: flex !important;\n width: 3px !important;\n height: 3px !important;\n min-width: 3px !important;\n min-height: 3px !important;\n border-radius: 50% !important;\n background: ".concat(avatarGrad2, " !important;\n background-color: ").concat(avatarGrad2, " !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 0.8s ease-in-out infinite !important;\n animation: ttp-pulse 0.8s ease-in-out infinite !important;\n }\n /* Orb waveform: same motion as shadow DOM (ttp-wave keyframes). Do not set opacity !important\n on bars \u2014 it overrides keyframe opacity and changes the look. */\n #ttp-widget-container .ttp-wave,\n #text-chat-panel .ttp-wave {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 26px !important;\n min-height: 26px !important;\n width: auto !important;\n min-width: 36px !important;\n overflow: visible !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-wave-bar,\n #text-chat-panel .ttp-wave-bar {\n display: block !important;\n box-sizing: content-box !important;\n width: 2.5px !important;\n min-width: 2.5px !important;\n max-width: none !important;\n flex-shrink: 0 !important;\n border-radius: 3px !important;\n background: rgba(255, 255, 255, 0.9) !important;\n background-color: rgba(255, 255, 255, 0.9) !important;\n visibility: visible !important;\n transform-origin: center center !important;\n -webkit-animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n }\n #ttp-widget-container .ttp-orb,\n #text-chat-panel .ttp-orb {\n overflow: visible !important;\n }\n ") : '', "\n .ttp-timer { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; letter-spacing: 0.05em").concat(important, "; }\n .ttp-call-label { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.25)").concat(important, "; }\n\n /* \u2500\u2500 ORB \u2500\u2500 */\n .ttp-orb-wrap {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; align-items: center").concat(important, ";\n gap: 12px").concat(important, "; padding: 8px 0").concat(important, ";\n }\n .ttp-orb-rings {\n position: relative").concat(important, "; width: 72px").concat(important, "; height: 72px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n }\n .ttp-ring {\n position: absolute").concat(important, "; border-radius: 50%").concat(important, ";\n border: 1.5px solid ").concat(primaryGrad1, "33;\n animation: ttp-ring 2s ease-in-out infinite").concat(important, ";\n }\n .ttp-ring-1 { inset: -8px").concat(important, "; }\n .ttp-ring-2 { inset: -16px").concat(important, "; border-width: 1px").concat(important, "; border-color: ").concat(primaryGrad1, "1a; animation-delay: 0.5s").concat(important, "; }\n .ttp-orb {\n width: 72px").concat(important, "; height: 72px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n animation: ttp-orb-breathe 1.4s ease-in-out infinite").concat(important, ";\n box-shadow: 0 6px 24px ").concat(primaryGrad1, "66;\n }\n .ttp-wave { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 3px").concat(important, "; height: 26px").concat(important, "; }\n .ttp-wave-bar {\n width: 2.5px").concat(important, "; border-radius: 3px").concat(important, "; background: rgba(255,255,255,0.9)").concat(important, ";\n animation: ttp-wave 0.75s ease-in-out infinite alternate").concat(important, ";\n }\n .ttp-listen-label { font-size: 12px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; }\n\n /* \u2500\u2500 CONTROLS \u2500\u2500 */\n .ttp-controls {\n padding: 16px 20px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 14px").concat(important, ";\n }\n .ttp-ctrl-btn {\n width: 42px").concat(important, "; height: 42px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.06)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n cursor: pointer").concat(important, "; display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, "; transition: background 0.2s").concat(important, ";\n position: relative").concat(important, ";\n }\n .ttp-ctrl-btn:hover { background: rgba(255,255,255,0.12)").concat(important, "; }\n .ttp-ctrl-btn.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, ";\n border-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n .ttp-end-btn {\n width: 52px").concat(important, "; height: 52px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(endCallColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: #fff").concat(important, "; transform: rotate(135deg)").concat(important, ";\n box-shadow: 0 4px 16px ").concat(endCallColor, "59;\n transition: background 0.2s").concat(important, ";\n }\n .ttp-end-btn:hover { background: ").concat(endCallColor, "; opacity: 0.85").concat(important, "; }\n\n /* Mute/speaker icon toggle */\n .desktop-mic-icon, .desktop-speaker-icon { display: block").concat(important, "; }\n .desktop-mic-off-icon, .desktop-speaker-off-icon {\n position: absolute").concat(important, "; top: 50%").concat(important, "; left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, "; z-index: 10").concat(important, ";\n }\n\n /* \u2500\u2500 DESKTOP VOICE SECTION WRAPPER \u2500\u2500 */\n .desktop-voice-section { flex-shrink: 0").concat(important, "; }\n\n /* \u2500\u2500 COMPACT VOICE SECTION (shown when items/rooms are visible) \u2500\u2500 */\n .compact-voice-section {\n padding: 10px 14px").concat(important, ";\n background: linear-gradient(180deg, ").concat(heroGrad1, " 0%, ").concat(primaryGrad1, "14 100%);\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n flex-shrink: 0").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .compact-left { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .compact-avatar {\n width: 42px").concat(important, "; height: 42px").concat(important, "; min-width: 42px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .compact-orb {\n width: 32px !important; height: 32px !important;\n border-radius: 50% !important;\n }\n .compact-info { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, "; }\n .compact-timer {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; font-weight: 600").concat(important, "; color: #e8e4f0").concat(important, ";\n }\n .compact-status {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, ";\n }\n .compact-controls { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 6px").concat(important, "; }\n .compact-control-btn {\n width: 36px").concat(important, "; height: 36px").concat(important, "; min-width: 36px").concat(important, ";\n border-radius: 50%").concat(important, "; border: none").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n cursor: pointer").concat(important, "; transition: all 0.15s").concat(important, ";\n position: relative").concat(important, ";\n }\n .compact-control-btn svg { width: 16px").concat(important, "; height: 16px").concat(important, "; }\n .compact-control-btn .desktop-mic-off-icon,\n .compact-control-btn .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.secondary {\n background: rgba(255,255,255,0.08)").concat(important, "; color: rgba(255,255,255,0.5)").concat(important, ";\n }\n .compact-control-btn.secondary:hover {\n background: rgba(255,255,255,0.14)").concat(important, "; color: rgba(255,255,255,0.7)").concat(important, ";\n }\n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, "; color: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.danger {\n width: 40px").concat(important, "; height: 40px").concat(important, "; min-width: 40px").concat(important, ";\n background: #ef4444").concat(important, "; color: #fff").concat(important, ";\n box-shadow: 0 3px 10px rgba(239,68,68,0.35)").concat(important, ";\n }\n .compact-control-btn.danger:hover {\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 4px 14px rgba(239,68,68,0.45)").concat(important, ";\n }\n .compact-control-btn.danger svg { width: 18px").concat(important, "; height: 18px").concat(important, "; overflow: visible").concat(important, "; }\n\n /* \u2500\u2500 TRANSCRIPT \u2500\u2500 */\n .ttp-transcript {\n margin: 0 16px 16px").concat(important, ";\n padding: 12px 14px").concat(important, ";\n background: ").concat(primaryGrad1, "24;\n border: 1px solid ").concat(primaryGrad1, "4d;\n border-radius: 12px").concat(important, ";\n }\n .ttp-transcript-hdr {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 7px").concat(important, ";\n }\n .ttp-live-label {\n font-size: 10px").concat(important, "; color: ").concat(primaryGrad2, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.1em").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n .ttp-toggle-text {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.35)").concat(important, ";\n cursor: pointer").concat(important, "; margin-left: auto").concat(important, "; margin-right: 8px").concat(important, ";\n transition: color 0.2s").concat(important, ";\n }\n .ttp-toggle-text:hover { color: ").concat(primaryGrad2, "; }\n .ttp-transcript-hdr { cursor: pointer").concat(important, "; }\n .ttp-dots { display: flex").concat(important, "; gap: 3px").concat(important, "; align-items: center").concat(important, "; }\n .ttp-dot {\n width: 3px").concat(important, "; height: 3px").concat(important, "; border-radius: 50%").concat(important, "; background: ").concat(primaryGrad2, ";\n animation: ttp-pulse 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .ttp-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n .ttp-transcript-text { font-size: 12px").concat(important, "; color: #e2e0f0").concat(important, "; line-height: 1.55").concat(important, "; }\n .ttp-transcript-text .name { color: #c4b5fd").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-left: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n\n /* Transcript collapsed/expanded state */\n .live-transcript-collapsed { display: block").concat(important, "; }\n .conversation-history { display: none").concat(important, "; }\n\n .ttp-transcript.expanded {\n flex: 1").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-transcript.expanded .live-transcript-collapsed { display: none").concat(important, "; }\n .ttp-transcript.expanded .conversation-history {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n max-height: 260px").concat(important, ";\n scrollbar-width: thin").concat(important, ";\n scrollbar-color: ").concat(primaryGrad1, "4d transparent;\n }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar { width: 4px").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-track { background: transparent").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-thumb {\n background: ").concat(primaryGrad1, "4d; border-radius: 2px").concat(important, ";\n }\n\n /* Message rows in history */\n .conversation-messages { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 8px").concat(important, "; padding-bottom: 4px").concat(important, "; }\n .message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n animation: ttp-msg-in 0.2s ease-out").concat(important, ";\n }\n .message-row.user { flex-direction: row-reverse").concat(important, "; }\n .message-avatar {\n width: 26px").concat(important, "; height: 26px").concat(important, "; min-width: 26px").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 10px").concat(important, "; font-weight: 600").concat(important, "; flex-shrink: 0").concat(important, ";\n }\n .message-avatar.user {\n background: rgba(255,255,255,0.12)").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n }\n .message-avatar.assistant {\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n }\n .message-avatar .orb {\n width: 12px").concat(important, "; height: 12px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.9)").concat(important, ";\n }\n .message-bubble {\n padding: 8px 12px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .message-row.assistant .message-bubble {\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n .message-row.user .message-bubble {\n background: ").concat(primaryGrad1, "40;\n color: #e8e4f0").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n .live-message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n margin-top: 6px").concat(important, ";\n }\n .live-message-row .message-bubble {\n position: relative").concat(important, ";\n padding: 14px 12px 8px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .live-message-row .live-badge {\n position: absolute").concat(important, "; top: 0").concat(important, "; left: 10px").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n background: ").concat(primaryGrad1, "; color: #fff").concat(important, ";\n font-size: 8px").concat(important, "; font-weight: 700").concat(important, ";\n padding: 2px 6px").concat(important, "; border-radius: 4px").concat(important, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.05em").concat(important, ";\n }\n .typing-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-left: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n @keyframes ttp-msg-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* \u2500\u2500 TYPE ROW \u2500\u2500 */\n .ttp-type-row { display: flex").concat(important, "; gap: 8px").concat(important, "; padding: 0 16px 16px").concat(important, "; flex-wrap: wrap").concat(important, "; }\n .ttp-input {\n flex: 1").concat(important, "; padding: 9px 12px").concat(important, ";\n background: rgba(255,255,255,0.05)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n border-radius: 10px").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n font-size: 12px").concat(important, "; outline: none").concat(important, "; font-family: inherit").concat(important, ";\n transition: border-color 0.2s").concat(important, ";\n }\n .ttp-input::placeholder { color: rgba(255,255,255,0.25)").concat(important, "; }\n .ttp-input:focus { border-color: ").concat(primaryGrad1, "80; }\n .ttp-send-btn {\n width: 34px").concat(important, "; height: 34px").concat(important, "; border-radius: 9px").concat(important, ";\n background: ").concat(sendBtnColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, "; transition: background 0.2s").concat(important, ";\n }\n .ttp-send-btn:hover { background: ").concat(sendBtnColor, "; opacity: 0.85").concat(important, "; }\n\n /* \u2500\u2500 KEYFRAMES \u2500\u2500 */\n @keyframes ttp-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }\n @keyframes ttp-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }\n @keyframes ttp-ring { 0%,100%{transform:scale(1);opacity:.6} 50%{transform:scale(1.22);opacity:0} }\n @keyframes ttp-orb-breathe { 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }\n @keyframes ttp-wave { from{transform:scaleY(.15);opacity:.3} to{transform:scaleY(1);opacity:.9} }\n @keyframes ttp-pill-pulse { 0%,100%{box-shadow:0 0 0 0 ").concat(primaryGrad1, "80} 60%{box-shadow:0 0 0 7px ").concat(primaryGrad1, "00} }\n\n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n\n ");
|
|
36334
|
+
var callSurfaceGradient = "linear-gradient(160deg, ".concat(heroGrad1, " 0%, ").concat(heroGrad2, " 100%)");
|
|
36335
|
+
return "\n /* Voice Interface - Dark Theme Desktop */\n .voice-interface {\n display: none".concat(important, ";\n flex: 1").concat(important, ";\n flex-direction: column").concat(important, ";\n align-items: stretch").concat(important, ";\n justify-content: flex-start").concat(important, ";\n padding: 0").concat(important, ";\n background: ").concat(panelBg, ";\n overflow: hidden").concat(important, ";\n min-height: 0").concat(important, ";\n height: 100%").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .voice-interface.active {\n display: flex").concat(important, ";\n background: ").concat(callSurfaceGradient).concat(important, ";\n }\n\n .voice-interface.active:has(#voiceIdleState:not([style*=\"display: none\"]):not([style*=\"display:none\"])) {\n background: transparent").concat(important, ";\n }\n\n /* Footer: same in-call purple as voice area (parent also sets bg; this covers any layout gaps) */\n .voice-interface.active ~ .ttp-footer {\n background: ").concat(callSurfaceGradient).concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n .voice-interface.active ~ .ttp-footer span { color: rgba(255,255,255,0.35)").concat(important, "; }\n .voice-interface.active ~ .ttp-footer a { color: ").concat(talkToPcFooterLink).concat(important, "; }\n\n #voiceIdleState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n width: 100%").concat(important, ";\n box-sizing: border-box").concat(important, ";\n background: transparent").concat(important, ";\n }\n #voiceIdleState[style*=\"display: none\"],\n #voiceIdleState[style*=\"display:none\"] {\n display: none !important;\n }\n\n #voiceActiveState {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n flex: 1").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n #voiceActiveState[style*=\"display: none\"],\n #voiceActiveState[style*=\"display:none\"] {\n display: none !important;\n }\n\n /* \u2500\u2500 IDLE HERO \u2014 transparent; gradient is on #voiceIdleState so hero + body share one surface \u2500\u2500 */\n .ttp-hero {\n position: relative").concat(important, ";\n padding: 24px 22px 22px").concat(important, ";\n background: transparent").concat(important, ";\n border-bottom: none").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-hero::after {\n content: ''").concat(important, ";\n position: absolute").concat(important, ";\n top: -40px").concat(important, "; right: -40px").concat(important, ";\n width: 140px").concat(important, "; height: 140px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: radial-gradient(circle, ").concat(primaryGrad1, "2e 0%, transparent 70%);\n pointer-events: none").concat(important, ";\n }\n .ttp-header {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n margin-bottom: 20px").concat(important, ";\n position: relative").concat(important, ";\n z-index: 1").concat(important, ";\n }\n .ttp-agent { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .ttp-avatar-wrap { position: relative").concat(important, "; }\n .ttp-avatar {\n width: 36px").concat(important, "; height: 36px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: #fff").concat(important, ";\n }\n .ttp-avatar.ttp-avatar--image {\n padding: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-avatar-img {\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n object-fit: cover").concat(important, ";\n display: block").concat(important, ";\n border-radius: 50%").concat(important, ";\n }\n .ttp-online-dot {\n position: absolute").concat(important, "; bottom: 0").concat(important, "; right: 0").concat(important, ";\n width: 10px").concat(important, "; height: 10px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(onlineDotColor, "; border: 2px solid ").concat(heroGrad2, ";\n }\n .ttp-agent-name { font-size: 14px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(agentNameColor, "; }\n .ttp-agent-role { font-size: 10px").concat(important, "; color: ").concat(agentRoleColor, "; margin-top: 1px").concat(important, "; }\n .ttp-close-btn {\n width: 26px").concat(important, "; height: 26px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.07)").concat(important, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n transition: background 0.2s").concat(important, ";\n }\n .ttp-close-btn:hover { background: rgba(255,255,255,0.14)").concat(important, "; }\n .ttp-headline {\n font-size: 22px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(headlineColor, ";\n line-height: 1.2").concat(important, "; margin-bottom: 6px").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n .ttp-subline {\n font-size: 13px").concat(important, "; color: ").concat(sublineColor, ";\n line-height: 1.5").concat(important, "; position: relative").concat(important, "; z-index: 1").concat(important, ";\n }\n\n /* \u2500\u2500 DOMAIN ERROR CARD \u2500\u2500 */\n .ttp-domain-error-card {\n display: flex").concat(important, ";\n align-items: flex-start").concat(important, ";\n gap: 12px").concat(important, ";\n padding: 14px 16px").concat(important, ";\n border-radius: 12px").concat(important, ";\n background: rgba(239,68,68,0.08)").concat(important, ";\n border: 1px solid rgba(239,68,68,0.18)").concat(important, ";\n }\n .ttp-domain-error-icon {\n flex-shrink: 0").concat(important, ";\n margin-top: 1px").concat(important, ";\n }\n .ttp-domain-error-text {\n font-size: 12px").concat(important, ";\n line-height: 1.55").concat(important, ";\n color: rgba(252,165,165,0.85)").concat(important, ";\n }\n .ttp-domain-error-text strong {\n color: #fca5a5").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* \u2500\u2500 IDLE BODY \u2500\u2500 */\n .ttp-body {\n padding: 10px 18px 14px").concat(important, ";\n display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 6px").concat(important, ";\n }\n .ttp-btn-primary {\n width: 100%").concat(important, "; padding: 11px").concat(important, "; border-radius: 12px").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n border: none").concat(important, "; cursor: pointer").concat(important, ";\n font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: ").concat(primaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n box-shadow: 0 4px 18px ").concat(primaryGrad1, "59;\n transition: opacity 0.2s, transform 0.15s").concat(important, ";\n font-family: inherit").concat(important, ";\n }\n .ttp-btn-primary:hover { opacity: 0.9").concat(important, "; transform: translateY(-1px)").concat(important, "; }\n .ttp-btn-primary:disabled { cursor: not-allowed").concat(important, "; opacity: 0.6").concat(important, "; }\n .ttp-btn-secondary {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: ").concat(secondaryBg, ";\n border: 1px solid ").concat(secondaryBorder, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; color: ").concat(secondaryTextColor, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n }\n .ttp-btn-secondary:hover { background: ").concat(secondaryBg, "; }\n\n /* WhatsApp button */\n .ttp-btn-wa {\n width: 100%").concat(important, "; padding: 10px").concat(important, "; border-radius: 12px").concat(important, ";\n background: rgba(37,211,102,0.08)").concat(important, ";\n border: 1px solid rgba(37,211,102,0.2)").concat(important, ";\n cursor: pointer").concat(important, "; font-size: 13px").concat(important, "; font-weight: 500").concat(important, "; color: #4ade80").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 8px").concat(important, ";\n transition: background 0.2s").concat(important, "; font-family: inherit").concat(important, ";\n text-decoration: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n .ttp-btn-wa:hover { background: rgba(37,211,102,0.14)").concat(important, "; }\n\n /* Connecting Spinner (reused from old design) */\n .connecting-spinner {\n display: inline-block").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n border: 2px solid rgba(255,255,255,0.3)").concat(important, ";\n border-top-color: #fff").concat(important, ";\n border-radius: 50%").concat(important, ";\n animation: ttp-spin 1s linear infinite").concat(important, ";\n margin-right: 8px").concat(important, ";\n vertical-align: middle").concat(important, ";\n }\n @keyframes ttp-spin { to { transform: rotate(360deg); } }\n\n /* \u2500\u2500 ACTIVE CALL \u2500\u2500 */\n .ttp-call-hero {\n background: transparent").concat(important, ";\n padding: 22px 20px 18px").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .ttp-call-topbar {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 18px").concat(important, ";\n }\n .ttp-rec { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 7px").concat(important, "; }\n .ttp-rec-dot {\n width: 7px").concat(important, "; height: 7px").concat(important, "; border-radius: 50%").concat(important, "; background: #f87171").concat(important, ";\n animation: ttp-pulse 1s ease-in-out infinite").concat(important, ";\n }\n ").concat(this.config.useShadowDOM === false ? "\n /* Regular DOM (e.g. Shopify): theme rules often strip span/div sizing \u2014 recording dot + pulse */\n #ttp-widget-container .ttp-call-topbar .ttp-rec,\n #text-chat-panel .ttp-call-topbar .ttp-rec {\n display: flex !important;\n align-items: center !important;\n gap: 7px !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-rec-dot,\n #ttp-widget-container .compact-timer .ttp-rec-dot,\n #text-chat-panel .ttp-rec-dot,\n #text-chat-panel .compact-timer .ttp-rec-dot {\n display: block !important;\n flex-shrink: 0 !important;\n box-sizing: content-box !important;\n width: 7px !important;\n height: 7px !important;\n min-width: 7px !important;\n min-height: 7px !important;\n max-width: none !important;\n max-height: none !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n border-radius: 50% !important;\n background: #f87171 !important;\n background-color: #f87171 !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 1s ease-in-out infinite !important;\n animation: ttp-pulse 1s ease-in-out infinite !important;\n }\n #ttp-widget-container .ttp-transcript-hdr .ttp-dot,\n #text-chat-panel .ttp-transcript-hdr .ttp-dot {\n display: flex !important;\n width: 3px !important;\n height: 3px !important;\n min-width: 3px !important;\n min-height: 3px !important;\n border-radius: 50% !important;\n background: ".concat(avatarGrad2, " !important;\n background-color: ").concat(avatarGrad2, " !important;\n opacity: 1 !important;\n visibility: visible !important;\n -webkit-animation: ttp-pulse 0.8s ease-in-out infinite !important;\n animation: ttp-pulse 0.8s ease-in-out infinite !important;\n }\n /* Orb waveform: same motion as shadow DOM (ttp-wave keyframes). Do not set opacity !important\n on bars \u2014 it overrides keyframe opacity and changes the look. */\n #ttp-widget-container .ttp-wave,\n #text-chat-panel .ttp-wave {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 26px !important;\n min-height: 26px !important;\n width: auto !important;\n min-width: 36px !important;\n overflow: visible !important;\n flex-shrink: 0 !important;\n }\n #ttp-widget-container .ttp-wave-bar,\n #text-chat-panel .ttp-wave-bar {\n display: block !important;\n box-sizing: content-box !important;\n width: 2.5px !important;\n min-width: 2.5px !important;\n max-width: none !important;\n flex-shrink: 0 !important;\n border-radius: 3px !important;\n background: rgba(255, 255, 255, 0.9) !important;\n background-color: rgba(255, 255, 255, 0.9) !important;\n visibility: visible !important;\n transform-origin: center center !important;\n -webkit-animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n animation: ttp-wave 0.75s ease-in-out infinite alternate !important;\n }\n #ttp-widget-container .ttp-orb,\n #text-chat-panel .ttp-orb {\n overflow: visible !important;\n }\n ") : '', "\n .ttp-timer { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; letter-spacing: 0.05em").concat(important, "; }\n .ttp-call-label { font-size: 11px").concat(important, "; color: rgba(255,255,255,0.25)").concat(important, "; }\n\n /* \u2500\u2500 ORB \u2500\u2500 */\n .ttp-orb-wrap {\n display: flex").concat(important, "; flex-direction: column").concat(important, "; align-items: center").concat(important, ";\n gap: 12px").concat(important, "; padding: 8px 0").concat(important, ";\n }\n .ttp-orb-rings {\n position: relative").concat(important, "; width: 72px").concat(important, "; height: 72px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n }\n .ttp-ring {\n position: absolute").concat(important, "; border-radius: 50%").concat(important, ";\n border: 1.5px solid ").concat(primaryGrad1, "33;\n animation: ttp-ring 2s ease-in-out infinite").concat(important, ";\n }\n .ttp-ring-1 { inset: -8px").concat(important, "; }\n .ttp-ring-2 { inset: -16px").concat(important, "; border-width: 1px").concat(important, "; border-color: ").concat(primaryGrad1, "1a; animation-delay: 0.5s").concat(important, "; }\n .ttp-orb {\n width: 72px").concat(important, "; height: 72px").concat(important, "; border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(primaryGrad1, ", ").concat(primaryGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n animation: ttp-orb-breathe 1.4s ease-in-out infinite").concat(important, ";\n box-shadow: 0 6px 24px ").concat(primaryGrad1, "66;\n }\n .ttp-wave { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 3px").concat(important, "; height: 26px").concat(important, "; }\n .ttp-wave-bar {\n width: 2.5px").concat(important, "; border-radius: 3px").concat(important, "; background: rgba(255,255,255,0.9)").concat(important, ";\n animation: ttp-wave 0.75s ease-in-out infinite alternate").concat(important, ";\n }\n .ttp-listen-label { font-size: 12px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, "; }\n\n /* \u2500\u2500 CONTROLS \u2500\u2500 */\n .ttp-controls {\n padding: 16px 20px").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, "; gap: 14px").concat(important, ";\n }\n .ttp-ctrl-btn {\n width: 42px").concat(important, "; height: 42px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.06)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n cursor: pointer").concat(important, "; display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: rgba(255,255,255,0.4)").concat(important, "; transition: background 0.2s").concat(important, ";\n position: relative").concat(important, ";\n }\n .ttp-ctrl-btn:hover { background: rgba(255,255,255,0.12)").concat(important, "; }\n .ttp-ctrl-btn.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, ";\n border-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n .ttp-end-btn {\n width: 52px").concat(important, "; height: 52px").concat(important, "; border-radius: 50%").concat(important, ";\n background: ").concat(endCallColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n color: #fff").concat(important, "; transform: rotate(135deg)").concat(important, ";\n box-shadow: 0 4px 16px ").concat(endCallColor, "59;\n transition: background 0.2s").concat(important, ";\n }\n .ttp-end-btn:hover { background: ").concat(endCallColor, "; opacity: 0.85").concat(important, "; }\n\n /* Mute/speaker icon toggle */\n .desktop-mic-icon, .desktop-speaker-icon { display: block").concat(important, "; }\n .desktop-mic-off-icon, .desktop-speaker-off-icon {\n position: absolute").concat(important, "; top: 50%").concat(important, "; left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 16px").concat(important, "; height: 16px").concat(important, "; z-index: 10").concat(important, ";\n }\n\n /* \u2500\u2500 DESKTOP VOICE SECTION WRAPPER \u2500\u2500 */\n .desktop-voice-section { flex-shrink: 0").concat(important, "; }\n\n /* \u2500\u2500 COMPACT VOICE SECTION (shown when items/rooms are visible) \u2500\u2500 */\n .compact-voice-section {\n padding: 10px 14px").concat(important, ";\n background: transparent").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n flex-shrink: 0").concat(important, ";\n border-bottom: 1px solid rgba(255,255,255,0.06)").concat(important, ";\n }\n .compact-left { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 10px").concat(important, "; }\n .compact-avatar {\n width: 42px").concat(important, "; height: 42px").concat(important, "; min-width: 42px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .compact-orb {\n width: 32px !important; height: 32px !important;\n border-radius: 50% !important;\n }\n .compact-info { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 2px").concat(important, "; }\n .compact-timer {\n display: flex").concat(important, "; align-items: center").concat(important, "; gap: 5px").concat(important, ";\n font-size: 11px").concat(important, "; font-weight: 600").concat(important, "; color: #e8e4f0").concat(important, ";\n }\n .compact-status {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.4)").concat(important, ";\n }\n .compact-controls { display: flex").concat(important, "; align-items: center").concat(important, "; gap: 6px").concat(important, "; }\n .compact-control-btn {\n width: 36px").concat(important, "; height: 36px").concat(important, "; min-width: 36px").concat(important, ";\n border-radius: 50%").concat(important, "; border: none").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n cursor: pointer").concat(important, "; transition: all 0.15s").concat(important, ";\n position: relative").concat(important, ";\n }\n .compact-control-btn svg { width: 16px").concat(important, "; height: 16px").concat(important, "; }\n .compact-control-btn .desktop-mic-off-icon,\n .compact-control-btn .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.secondary {\n background: rgba(255,255,255,0.08)").concat(important, "; color: rgba(255,255,255,0.5)").concat(important, ";\n }\n .compact-control-btn.secondary:hover {\n background: rgba(255,255,255,0.14)").concat(important, "; color: rgba(255,255,255,0.7)").concat(important, ";\n }\n .compact-control-btn.secondary.muted {\n background: rgba(239, 68, 68, 0.15)").concat(important, "; color: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-icon {\n stroke: #ef4444").concat(important, ";\n }\n .compact-control-btn.secondary.muted .desktop-mic-off-icon,\n .compact-control-btn.secondary.muted .desktop-speaker-off-icon {\n width: 16px").concat(important, "; height: 16px").concat(important, ";\n }\n .compact-control-btn.danger {\n width: 40px").concat(important, "; height: 40px").concat(important, "; min-width: 40px").concat(important, ";\n background: #ef4444").concat(important, "; color: #fff").concat(important, ";\n box-shadow: 0 3px 10px rgba(239,68,68,0.35)").concat(important, ";\n }\n .compact-control-btn.danger:hover {\n transform: scale(1.05)").concat(important, ";\n box-shadow: 0 4px 14px rgba(239,68,68,0.45)").concat(important, ";\n }\n .compact-control-btn.danger svg { width: 18px").concat(important, "; height: 18px").concat(important, "; overflow: visible").concat(important, "; }\n\n /* \u2500\u2500 TRANSCRIPT \u2500\u2500 */\n .ttp-transcript {\n margin: 0 16px 16px").concat(important, ";\n padding: 12px 14px").concat(important, ";\n background: ").concat(primaryGrad1, "24;\n border: 1px solid ").concat(primaryGrad1, "4d;\n border-radius: 12px").concat(important, ";\n }\n .ttp-transcript-hdr {\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: space-between").concat(important, ";\n margin-bottom: 7px").concat(important, ";\n }\n .ttp-live-label {\n font-size: 10px").concat(important, "; color: ").concat(primaryGrad2, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.1em").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n .ttp-toggle-text {\n font-size: 10px").concat(important, "; color: rgba(255,255,255,0.35)").concat(important, ";\n cursor: pointer").concat(important, "; margin-left: auto").concat(important, "; margin-right: 8px").concat(important, ";\n transition: color 0.2s").concat(important, ";\n }\n .ttp-toggle-text:hover { color: ").concat(primaryGrad2, "; }\n .ttp-transcript-hdr { cursor: pointer").concat(important, "; }\n .ttp-dots { display: flex").concat(important, "; gap: 3px").concat(important, "; align-items: center").concat(important, "; }\n .ttp-dot {\n width: 3px").concat(important, "; height: 3px").concat(important, "; border-radius: 50%").concat(important, "; background: ").concat(primaryGrad2, ";\n animation: ttp-pulse 0.8s ease-in-out infinite").concat(important, ";\n }\n .ttp-dot:nth-child(2) { animation-delay: 0.2s").concat(important, "; }\n .ttp-dot:nth-child(3) { animation-delay: 0.4s").concat(important, "; }\n .ttp-transcript-text {\n font-size: 12px").concat(important, "; color: #e2e0f0").concat(important, "; line-height: 1.55").concat(important, ";\n unicode-bidi: isolate").concat(important, ";\n text-align: start").concat(important, ";\n }\n .ttp-transcript-text .name { color: #c4b5fd").concat(important, "; font-weight: 600").concat(important, "; }\n .ttp-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-inline-start: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n\n /* Transcript collapsed/expanded state */\n .live-transcript-collapsed { display: block").concat(important, "; }\n .conversation-history { display: none").concat(important, "; }\n\n .ttp-transcript.expanded {\n flex: 1").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .ttp-transcript.expanded .live-transcript-collapsed { display: none").concat(important, "; }\n .ttp-transcript.expanded .conversation-history {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n max-height: 260px").concat(important, ";\n scrollbar-width: thin").concat(important, ";\n scrollbar-color: ").concat(primaryGrad1, "4d transparent;\n }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar { width: 4px").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-track { background: transparent").concat(important, "; }\n .ttp-transcript.expanded .conversation-history::-webkit-scrollbar-thumb {\n background: ").concat(primaryGrad1, "4d; border-radius: 2px").concat(important, ";\n }\n\n /* Message rows in history */\n .conversation-messages { display: flex").concat(important, "; flex-direction: column").concat(important, "; gap: 8px").concat(important, "; padding-bottom: 4px").concat(important, "; }\n .message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n animation: ttp-msg-in 0.2s ease-out").concat(important, ";\n }\n .message-row.user { flex-direction: row-reverse").concat(important, "; }\n .message-avatar {\n width: 26px").concat(important, "; height: 26px").concat(important, "; min-width: 26px").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n font-size: 10px").concat(important, "; font-weight: 600").concat(important, "; flex-shrink: 0").concat(important, ";\n }\n .message-avatar.user {\n background: rgba(255,255,255,0.12)").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n }\n .message-avatar.assistant {\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ");\n }\n .message-avatar .orb {\n width: 12px").concat(important, "; height: 12px").concat(important, "; border-radius: 50%").concat(important, ";\n background: rgba(255,255,255,0.9)").concat(important, ";\n }\n .message-bubble {\n padding: 8px 12px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n }\n .message-row.assistant .message-bubble {\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n .message-row.user .message-bubble {\n background: ").concat(primaryGrad1, "40;\n color: #e8e4f0").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n .live-message-row {\n display: flex").concat(important, "; align-items: flex-start").concat(important, "; gap: 8px").concat(important, ";\n margin-top: 6px").concat(important, ";\n }\n .live-message-row .message-bubble {\n position: relative").concat(important, ";\n padding: 14px 12px 8px").concat(important, ";\n border-radius: 12px").concat(important, ";\n font-size: 12px").concat(important, "; line-height: 1.5").concat(important, ";\n background: rgba(255,255,255,0.08)").concat(important, ";\n color: #e2e0f0").concat(important, ";\n max-width: 80%").concat(important, "; word-wrap: break-word").concat(important, ";\n }\n .live-message-row .live-badge {\n position: absolute").concat(important, "; top: 0").concat(important, "; left: 10px").concat(important, ";\n transform: translateY(-50%)").concat(important, ";\n background: ").concat(primaryGrad1, "; color: #fff").concat(important, ";\n font-size: 8px").concat(important, "; font-weight: 700").concat(important, ";\n padding: 2px 6px").concat(important, "; border-radius: 4px").concat(important, ";\n text-transform: uppercase").concat(important, "; letter-spacing: 0.05em").concat(important, ";\n }\n .typing-cursor {\n display: inline-block").concat(important, "; width: 2px").concat(important, "; height: 12px").concat(important, ";\n background: ").concat(primaryGrad2, "; vertical-align: middle").concat(important, "; margin-inline-start: 2px").concat(important, ";\n animation: ttp-blink 0.9s infinite").concat(important, ";\n }\n @keyframes ttp-msg-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n /* \u2500\u2500 TYPE ROW \u2500\u2500 */\n .ttp-type-row { display: flex").concat(important, "; gap: 8px").concat(important, "; padding: 0 16px 16px").concat(important, "; flex-wrap: wrap").concat(important, "; }\n .ttp-input {\n flex: 1").concat(important, "; padding: 9px 12px").concat(important, ";\n background: rgba(255,255,255,0.05)").concat(important, ";\n border: 1px solid rgba(255,255,255,0.09)").concat(important, ";\n border-radius: 10px").concat(important, "; color: rgba(255,255,255,0.6)").concat(important, ";\n font-size: 12px").concat(important, "; outline: none").concat(important, "; font-family: inherit").concat(important, ";\n transition: border-color 0.2s").concat(important, ";\n text-align: start").concat(important, ";\n }\n .ttp-input::placeholder { color: rgba(255,255,255,0.25)").concat(important, "; }\n .ttp-input:focus { border-color: ").concat(primaryGrad1, "80; }\n .ttp-send-btn {\n width: 34px").concat(important, "; height: 34px").concat(important, "; border-radius: 9px").concat(important, ";\n background: ").concat(sendBtnColor, "; border: none").concat(important, "; cursor: pointer").concat(important, ";\n display: flex").concat(important, "; align-items: center").concat(important, "; justify-content: center").concat(important, ";\n flex-shrink: 0").concat(important, "; transition: background 0.2s").concat(important, ";\n }\n .ttp-send-btn:hover { background: ").concat(sendBtnColor, "; opacity: 0.85").concat(important, "; }\n\n /* \u2500\u2500 KEYFRAMES \u2500\u2500 */\n @keyframes ttp-pulse { 0%,100%{opacity:1} 50%{opacity:.3} }\n @keyframes ttp-blink { 0%,49%{opacity:1} 50%,100%{opacity:0} }\n @keyframes ttp-ring { 0%,100%{transform:scale(1);opacity:.6} 50%{transform:scale(1.22);opacity:0} }\n @keyframes ttp-orb-breathe { 0%,100%{transform:scale(1)} 50%{transform:scale(1.05)} }\n @keyframes ttp-wave { from{transform:scaleY(.15);opacity:.3} to{transform:scaleY(1);opacity:.9} }\n @keyframes ttp-pill-pulse { 0%,100%{box-shadow:0 0 0 0 ").concat(primaryGrad1, "80} 60%{box-shadow:0 0 0 7px ").concat(primaryGrad1, "00} }\n\n /* Mobile Voice Call UI - Shared styles (also used in generateMobileCSS) */\n ").concat(this._getSharedMobileCSS(important), "\n\n ");
|
|
36090
36336
|
}
|
|
36091
36337
|
|
|
36092
36338
|
/**
|
|
@@ -36096,7 +36342,18 @@ var Styles = /*#__PURE__*/function () {
|
|
|
36096
36342
|
}, {
|
|
36097
36343
|
key: "_getSharedMobileCSS",
|
|
36098
36344
|
value: function _getSharedMobileCSS(important) {
|
|
36099
|
-
return "\n .mobile-duration-dot {\ndisplay: block !important;\n width: 6px".concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #ef4444").concat(important, ";\n animation: mobilePulse 1.5s ease-in-out infinite").concat(important, ";\n }\n\n @keyframes mobilePulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.95); }\n }\n\n .mobile-voice-bar {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 14px").concat(important, ";\n position: relative").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 50%, #c084fc 100%)").concat(important, ";\n border-radius: 24px 24px 0 0").concat(important, ";\n box-shadow: 0 -8px 32px rgba(124, 58, 237, 0.5), 0 -2px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.2)").concat(important, ";\n width: 100% !important;\n max-width: 100% !important;\n pointer-events: auto").concat(important, ";\n overflow: hidden !important;\n margin: 0 !important;\n }\n\n .mobile-top-row {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n position: relative").concat(important, ";\n }\n\n .mobile-status-indicator {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n min-width: 85px").concat(important, ";\n }\n\n .mobile-status-dot {\ndisplay: block !important;\n width: 7px").concat(important, ";\n height: 7px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 8px #22c55e").concat(important, ";\n transition: all 0.3s ease").concat(important, ";\n }\n\n .mobile-status-text {\n font-size: 11px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.95)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.3px").concat(important, ";\n }\n\n .mobile-waveform-center {\n position: absolute !important;\n left: 50% !important;\n transform: translateX(-50%) !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 24px !important;\n visibility: visible !important;\n }\n\n .mobile-waveform-bars {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n }\n\n .mobile-waveform-bar {\n display: block !important;\n width: 4px !important;\n min-height: 4px !important;\n background-color: #fff !important;\n border-radius: 2px !important;\n transition: height 0.12s ease-out !important;\n box-shadow: 0 0 8px rgba(255,255,255,0.5) !important;\n visibility: visible !important;\n }\n\n .mobile-controls {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n pointer-events: auto").concat(important, ";\n touch-action: manipulation").concat(important, ";\n position: relative").concat(important, ";\n z-index: 120").concat(important, ";\n }\n\n .mobile-control-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n min-width: 32px").concat(important, ";\n min-height: 32px").concat(important, ";\n max-width: 32px").concat(important, ";\n max-height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n background-color: rgba(255,255,255,0.15)").concat(important, ";\n position: relative").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-control-btn:hover {\n background-color: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-control-btn.muted {\n background-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n\n .mobile-control-btn .mobile-mic-icon,\n .mobile-control-btn .mobile-speaker-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-control-btn .mobile-mic-off-icon,\n .mobile-control-btn .mobile-speaker-off-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-control-btn:not(.muted) .mobile-mic-off-icon,\n .mobile-control-btn:not(.muted) .mobile-speaker-off-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-off-icon,\n .mobile-control-btn.muted .mobile-speaker-off-icon {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n\n .mobile-end-call-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n min-width: 36px").concat(important, ";\n min-height: 36px").concat(important, ";\n max-width: 36px").concat(important, ";\n max-height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n background-color: #ef4444").concat(important, ";\n box-shadow: 0 4px 14px rgba(239, 68, 68, 0.5)").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-end-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n\n /* ID-specific selectors for WordPress/Shopify compatibility */\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn,\n #mobileEndCallBtn.mobile-end-call-btn {\n border-radius: 50% !important;\n overflow: hidden !important;\n pointer-events: auto !important;\n touch-action: manipulation !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n text-decoration: none !important;\n line-height: 1 !important;\n font-size: 0 !important;\n letter-spacing: 0 !important;\n text-indent: 0 !important;\n text-transform: none !important;\n color: transparent !important;\n }\n\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn {\n width: 32px !important;\n height: 32px !important;\n min-width: 32px !important;\n min-height: 32px !important;\n max-width: 32px !important;\n max-height: 32px !important;\n }\n\n #mobileEndCallBtn.mobile-end-call-btn {\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n max-height: 36px !important;\n }\n\n #mobileMuteBtn.mobile-control-btn .mobile-mic-icon,\n #mobileMuteBtn.mobile-control-btn .mobile-mic-off-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-off-icon,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n width: 15px !important;\n height: 15px !important;\n max-width: 15px !important;\n max-height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n pointer-events: none !important;\n overflow: visible !important;\n }\n\n #mobile-voice-call-bar-container svg path,\n #mobile-voice-call-bar-container svg line,\n #mobile-voice-call-bar-container svg polygon,\n #mobile-voice-call-bar-container svg circle {\n pointer-events: none !important;\n vector-effect: none !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-transcript-row {\n width: 100%").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: rgba(255,255,255,0.18)").concat(important, ";\n border-radius: 14px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n text-align: left").concat(important, ";\n backdrop-filter: blur(4px)").concat(important, ";\n transition: background 0.2s ease").concat(important, ";\n pointer-events: auto !important;\n position: relative !important;\n z-index: 100 !important;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-transcript-text {\n margin: 0").concat(important, ";\n font-size: 13px").concat(important, ";\n color: #fff").concat(important, ";\n line-height: 1.4").concat(important, ";\n font-weight: 500").concat(important, ";\n display: -webkit-box !important;\n -webkit-line-clamp: 2 !important;\n -webkit-box-orient: vertical !important;\n overflow: hidden !important;\n min-height: 2.8em !important;\n }\n\n .mobile-transcript-footer {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n\n .mobile-expand-hint {\n font-size: 10px").concat(important, ";\n color: rgba(255,255,255,0.6)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n .mobile-transcript-overlay {\n position: fixed").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n bottom: 0").concat(important, ";\n background-color: rgba(0,0,0,0.6)").concat(important, ";\n display: flex").concat(important, ";\n align-items: flex-end").concat(important, ";\n padding: 12px").concat(important, ";\n z-index: 2147483647").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n .mobile-expanded-transcript {\n width: 100%").concat(important, ";\n max-height: 75%").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px 24px 16px 16px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3)").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n }\n\n .mobile-transcript-header {\n display: flex").concat(important, ";\n justify-content: space-between").concat(important, ";\n align-items: center").concat(important, ";\n padding: 14px 16px").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-header-left {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 2px").concat(important, ";\n }\n\n .mobile-header-status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n }\n\n .mobile-header-status-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 6px #22c55e").concat(important, ";\n }\n\n .mobile-header-status-text {\n font-size: 10px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.9)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n }\n\n .mobile-header-duration {\n font-size: 10px").concat(important, ";\n font-weight: 600").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n margin-left: 8px").concat(important, ";\n }\n\n .mobile-transcript-label {\n font-size: 11px").concat(important, ";\n font-weight: 800").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n letter-spacing: 1px").concat(important, ";\n }\n\n .mobile-close-transcript-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: rgba(255,255,255,0.2)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3)").concat(important, ";\n }\n\n .mobile-messages-container {\n flex: 1").concat(important, ";\n padding: 16px").concat(important, ";\n overflow-y: auto").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .mobile-message-bubble {\n max-width: 85%").concat(important, ";\n padding: 12px 16px").concat(important, ";\n border-radius: 18px").concat(important, ";\n font-size: 14px").concat(important, ";\n line-height: 1.5").concat(important, ";\n word-wrap: break-word").concat(important, ";\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start").concat(important, ";\n background-color: #f3f4f6").concat(important, ";\n color: #374151").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n color: #fff").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px").concat(important, ";\n border-top: 1px solid #e5e7eb").concat(important, ";\n background: #f9fafb").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-input-wrapper {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 4px 4px 4px 16px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px").concat(important, ";\n border: 2px solid #e5e7eb").concat(important, ";\n }\n\n .mobile-text-input {\n flex: 1").concat(important, ";\n border: none").concat(important, ";\n outline: none").concat(important, ";\n font-size: 14px").concat(important, ";\n color: #374151").concat(important, ";\n background: transparent").concat(important, ";\n padding: 10px 0").concat(important, ";\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af").concat(important, ";\n }\n\n .mobile-send-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: linear-gradient(135deg, #7c3aed 0%, #a855f7 100%)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n .mobile-input-hint {\n margin: 8px 0 0").concat(important, ";\n font-size: 11px").concat(important, ";\n color: #9ca3af").concat(important, ";\n text-align: center").concat(important, ";\n transition: color 0.2s ease").concat(important, ";\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666").concat(important, ";\n }\n\n .mobile-input-hint--success {\n color: #28a745").concat(important, ";\n }\n\n .mobile-input-hint--queued {\n color: #ffc107").concat(important, ";\n }\n\n .mobile-input-hint--error {\n color: #dc3545").concat(important, ";\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n ");
|
|
36345
|
+
var c = this.config;
|
|
36346
|
+
var avatarGrad1 = c.avatarGradient1 || '#6d56f5';
|
|
36347
|
+
var avatarGrad2 = c.avatarGradient2 || '#a78bfa';
|
|
36348
|
+
/* Match .ttp-mobile-landing / mobile FAB (TTPChatWidget pillGradient) — not desktop hero/call surface */
|
|
36349
|
+
var mobileLandingSurface = c.pillGradient || 'linear-gradient(135deg, #581c87, #312e81, #1e1b4b)';
|
|
36350
|
+
/* Primary = Start Call CTA — user bubbles + send only */
|
|
36351
|
+
var primaryGrad1 = c.primaryBtnGradient1 || c.startCallButtonColor || '#6d56f5';
|
|
36352
|
+
var primaryGrad2 = c.primaryBtnGradient2 || c.startCallButtonColor || '#9d8df8';
|
|
36353
|
+
var sendBtnColor = c.sendButtonColor || primaryGrad1;
|
|
36354
|
+
var endCallColor = c.endCallButtonColor || '#ef4444';
|
|
36355
|
+
var mobileAccentGradient = "linear-gradient(135deg, ".concat(sendBtnColor, ", ").concat(primaryGrad2, ")");
|
|
36356
|
+
return "\n /* Mobile voice idle: optional header image replaces \uD83E\uDD16 */\n .mobile-voice-interface #voiceIdleState .voice-avatar {\n width: 80px".concat(important, ";\n height: 80px").concat(important, ";\n margin: 12px auto 16px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background: linear-gradient(135deg, ").concat(avatarGrad1, ", ").concat(avatarGrad2, ")").concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n font-size: 40px").concat(important, ";\n line-height: 1").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-avatar.voice-avatar--image {\n padding: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-avatar-img {\n width: 100%").concat(important, ";\n height: 100%").concat(important, ";\n object-fit: cover").concat(important, ";\n border-radius: 50%").concat(important, ";\n display: block").concat(important, ";\n }\n\n /* Idle hero copy: light text on dark / gradient panels (host themes often force dark body color) */\n .mobile-voice-interface #voiceIdleState .voice-status {\n text-align: center").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-status-title {\n color: rgba(255,255,255,0.96)").concat(important, ";\n }\n .mobile-voice-interface #voiceIdleState .voice-status-subtitle {\n color: rgba(255,255,255,0.78)").concat(important, ";\n }\n\n .mobile-duration-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #ef4444").concat(important, ";\n animation: mobilePulse 1.5s ease-in-out infinite").concat(important, ";\n }\n\n @keyframes mobilePulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.95); }\n }\n\n .mobile-voice-bar {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 10px").concat(important, ";\n padding: 14px").concat(important, ";\n position: relative").concat(important, ";\n background: ").concat(mobileLandingSurface).concat(important, ";\n border-radius: 24px 24px 0 0").concat(important, ";\n box-shadow:\n 0 -8px 32px rgba(0, 0, 0, 0.3),\n 0 -2px 8px rgba(0, 0, 0, 0.35),\n inset 0 1px 0 rgba(255, 255, 255, 0.1)").concat(important, ";\n width: 100% !important;\n max-width: 100% !important;\n pointer-events: auto").concat(important, ";\n overflow: hidden !important;\n margin: 0 !important;\n }\n\n .mobile-top-row {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n position: relative").concat(important, ";\n }\n\n .mobile-status-indicator {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 5px").concat(important, ";\n min-width: 85px").concat(important, ";\n }\n\n .mobile-status-dot {\ndisplay: block !important;\n width: 7px").concat(important, ";\n height: 7px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 8px #22c55e").concat(important, ";\n transition: all 0.3s ease").concat(important, ";\n }\n\n .mobile-status-text {\n font-size: 11px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.95)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.3px").concat(important, ";\n }\n\n .mobile-waveform-center {\n position: absolute !important;\n left: 50% !important;\n transform: translateX(-50%) !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n height: 24px !important;\n visibility: visible !important;\n }\n\n .mobile-waveform-bars {\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 3px !important;\n }\n\n .mobile-waveform-bar {\n display: block !important;\n width: 4px !important;\n min-height: 4px !important;\n background-color: #fff !important;\n border-radius: 2px !important;\n transition: height 0.12s ease-out !important;\n box-shadow: 0 0 8px rgba(255,255,255,0.5) !important;\n visibility: visible !important;\n }\n\n .mobile-controls {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n pointer-events: auto").concat(important, ";\n touch-action: manipulation").concat(important, ";\n position: relative").concat(important, ";\n z-index: 120").concat(important, ";\n }\n\n .mobile-control-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n min-width: 32px").concat(important, ";\n min-height: 32px").concat(important, ";\n max-width: 32px").concat(important, ";\n max-height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n background-color: rgba(255,255,255,0.15)").concat(important, ";\n position: relative").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-control-btn:hover {\n background-color: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-control-btn.muted {\n background-color: rgba(239, 68, 68, 0.3)").concat(important, ";\n }\n\n .mobile-control-btn .mobile-mic-icon,\n .mobile-control-btn .mobile-speaker-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-control-btn .mobile-mic-off-icon,\n .mobile-control-btn .mobile-speaker-off-icon {\n position: absolute").concat(important, ";\n top: 50%").concat(important, ";\n left: 50%").concat(important, ";\n transform: translate(-50%, -50%)").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n }\n\n .mobile-control-btn:not(.muted) .mobile-mic-off-icon,\n .mobile-control-btn:not(.muted) .mobile-speaker-off-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-icon,\n .mobile-control-btn.muted .mobile-speaker-icon {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n }\n\n .mobile-control-btn.muted .mobile-mic-off-icon,\n .mobile-control-btn.muted .mobile-speaker-off-icon {\n display: block !important;\n visibility: visible !important;\n opacity: 1 !important;\n }\n\n .mobile-end-call-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 36px").concat(important, ";\n height: 36px").concat(important, ";\n min-width: 36px").concat(important, ";\n min-height: 36px").concat(important, ";\n max-width: 36px").concat(important, ";\n max-height: 36px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n background-color: ").concat(endCallColor).concat(important, ";\n box-shadow: 0 4px 14px ").concat(endCallColor, "80").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n overflow: hidden").concat(important, ";\n padding: 0").concat(important, ";\n margin: 0").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n .mobile-end-call-btn svg {\n display: block").concat(important, ";\n visibility: visible").concat(important, ";\n opacity: 1").concat(important, ";\n width: 15px").concat(important, ";\n height: 15px").concat(important, ";\n margin: 0").concat(important, ";\n padding: 0").concat(important, ";\n position: relative").concat(important, ";\n }\n\n /* ID-specific selectors for WordPress/Shopify compatibility */\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn,\n #mobileEndCallBtn.mobile-end-call-btn {\n border-radius: 50% !important;\n overflow: hidden !important;\n pointer-events: auto !important;\n touch-action: manipulation !important;\n -webkit-appearance: none !important;\n appearance: none !important;\n text-decoration: none !important;\n line-height: 1 !important;\n font-size: 0 !important;\n letter-spacing: 0 !important;\n text-indent: 0 !important;\n text-transform: none !important;\n color: transparent !important;\n }\n\n #mobileMuteBtn.mobile-control-btn,\n #mobileSpeakerBtn.mobile-control-btn {\n width: 32px !important;\n height: 32px !important;\n min-width: 32px !important;\n min-height: 32px !important;\n max-width: 32px !important;\n max-height: 32px !important;\n }\n\n #mobileEndCallBtn.mobile-end-call-btn {\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n max-height: 36px !important;\n }\n\n #mobileMuteBtn.mobile-control-btn .mobile-mic-icon,\n #mobileMuteBtn.mobile-control-btn .mobile-mic-off-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-icon,\n #mobileSpeakerBtn.mobile-control-btn .mobile-speaker-off-icon,\n #mobileEndCallBtn.mobile-end-call-btn svg {\n width: 15px !important;\n height: 15px !important;\n max-width: 15px !important;\n max-height: 15px !important;\n margin: 0 !important;\n padding: 0 !important;\n pointer-events: none !important;\n overflow: visible !important;\n }\n\n #mobile-voice-call-bar-container svg path,\n #mobile-voice-call-bar-container svg line,\n #mobile-voice-call-bar-container svg polygon,\n #mobile-voice-call-bar-container svg circle {\n pointer-events: none !important;\n vector-effect: none !important;\n }\n\n .mobile-end-call-btn:hover {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-transcript-row {\n width: 100%").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 6px").concat(important, ";\n padding: 10px 12px").concat(important, ";\n background: rgba(255,255,255,0.18)").concat(important, ";\n border-radius: 14px").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n text-align: start").concat(important, ";\n backdrop-filter: blur(4px)").concat(important, ";\n transition: background 0.2s ease").concat(important, ";\n pointer-events: auto !important;\n position: relative !important;\n z-index: 100 !important;\n }\n\n .mobile-transcript-row:hover {\n background: rgba(255,255,255,0.25)").concat(important, ";\n }\n\n .mobile-transcript-text {\n margin: 0").concat(important, ";\n font-size: 13px").concat(important, ";\n color: #fff").concat(important, ";\n line-height: 1.4").concat(important, ";\n font-weight: 500").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n display: -webkit-box !important;\n -webkit-line-clamp: 2 !important;\n -webkit-box-orient: vertical !important;\n overflow: hidden !important;\n min-height: 2.8em !important;\n }\n\n .mobile-transcript-footer {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n\n .mobile-expand-hint {\n font-size: 10px").concat(important, ";\n color: rgba(255,255,255,0.6)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n font-weight: 600").concat(important, ";\n }\n\n /* Base: hidden. Inline display:none loses to display:flex!important \u2014 use modifier for open state */\n .mobile-transcript-overlay {\n position: fixed").concat(important, ";\n top: 0").concat(important, ";\n left: 0").concat(important, ";\n right: 0").concat(important, ";\n bottom: 0").concat(important, ";\n background-color: rgba(0,0,0,0.6)").concat(important, ";\n display: none").concat(important, ";\n padding: 12px").concat(important, ";\n z-index: 2147483647").concat(important, ";\n pointer-events: auto").concat(important, ";\n }\n\n .mobile-transcript-overlay.mobile-transcript-overlay--open {\n display: flex").concat(important, ";\n align-items: flex-end").concat(important, ";\n }\n\n .mobile-expanded-transcript {\n width: 100%").concat(important, ";\n max-height: 75%").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px 24px 16px 16px").concat(important, ";\n overflow: hidden").concat(important, ";\n box-shadow: 0 -8px 40px rgba(0,0,0,0.3)").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n }\n\n .mobile-transcript-header {\n display: flex").concat(important, ";\n justify-content: space-between").concat(important, ";\n align-items: center").concat(important, ";\n padding: 14px 16px").concat(important, ";\n background: ").concat(mobileLandingSurface).concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-header-left {\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 2px").concat(important, ";\n }\n\n .mobile-header-status {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 6px").concat(important, ";\n }\n\n .mobile-header-status-dot {\ndisplay: block !important;\n width: 6px").concat(important, ";\n height: 6px").concat(important, ";\n border-radius: 50%").concat(important, ";\n background-color: #22c55e").concat(important, ";\n box-shadow: 0 0 6px #22c55e").concat(important, ";\n }\n\n .mobile-header-status-text {\n font-size: 10px").concat(important, ";\n font-weight: 700").concat(important, ";\n color: rgba(255,255,255,0.9)").concat(important, ";\n text-transform: uppercase").concat(important, ";\n letter-spacing: 0.5px").concat(important, ";\n }\n\n .mobile-header-duration {\n font-size: 10px").concat(important, ";\n font-weight: 600").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n margin-left: 8px").concat(important, ";\n }\n\n .mobile-transcript-label {\n font-size: 11px").concat(important, ";\n font-weight: 800").concat(important, ";\n color: rgba(255,255,255,0.7)").concat(important, ";\n letter-spacing: 1px").concat(important, ";\n }\n\n .mobile-close-transcript-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 32px").concat(important, ";\n height: 32px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: rgba(255,255,255,0.2)").concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n }\n\n .mobile-close-transcript-btn:hover {\n background: rgba(255,255,255,0.3)").concat(important, ";\n }\n\n .mobile-messages-container {\n flex: 1").concat(important, ";\n padding: 16px").concat(important, ";\n overflow-y: auto").concat(important, ";\n display: flex").concat(important, ";\n flex-direction: column").concat(important, ";\n gap: 12px").concat(important, ";\n }\n\n .mobile-message-bubble {\n max-width: 85%").concat(important, ";\n padding: 12px 16px").concat(important, ";\n border-radius: 18px").concat(important, ";\n font-size: 14px").concat(important, ";\n line-height: 1.5").concat(important, ";\n word-wrap: break-word").concat(important, ";\n unicode-bidi: plaintext").concat(important, ";\n text-align: start").concat(important, ";\n }\n\n .mobile-message-bubble.assistant {\n align-self: flex-start").concat(important, ";\n background-color: #f3f4f6").concat(important, ";\n color: #374151").concat(important, ";\n border-bottom-left-radius: 4px").concat(important, ";\n }\n\n .mobile-message-bubble.user {\n align-self: flex-end").concat(important, ";\n background: ").concat(mobileAccentGradient).concat(important, ";\n color: #fff").concat(important, ";\n border-bottom-right-radius: 4px").concat(important, ";\n }\n\n .mobile-input-area {\n padding: 12px 16px 16px").concat(important, ";\n border-top: 1px solid #e5e7eb").concat(important, ";\n background: #f9fafb").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n\n .mobile-input-wrapper {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 8px").concat(important, ";\n padding: 4px 4px 4px 16px").concat(important, ";\n background: #fff").concat(important, ";\n border-radius: 24px").concat(important, ";\n border: 2px solid #e5e7eb").concat(important, ";\n }\n\n .mobile-text-input {\n flex: 1").concat(important, ";\n border: none").concat(important, ";\n outline: none").concat(important, ";\n font-size: 14px").concat(important, ";\n color: #374151").concat(important, ";\n background: transparent").concat(important, ";\n padding: 10px 0").concat(important, ";\n text-align: start").concat(important, ";\n }\n\n .mobile-text-input::placeholder {\n color: #9ca3af").concat(important, ";\n }\n\n .mobile-send-btn {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n width: 40px").concat(important, ";\n height: 40px").concat(important, ";\n border-radius: 50%").concat(important, ";\n border: none").concat(important, ";\n background: ").concat(mobileAccentGradient).concat(important, ";\n color: #fff").concat(important, ";\n cursor: pointer").concat(important, ";\n transition: all 0.2s ease").concat(important, ";\n }\n\n .mobile-send-btn:hover:not(:disabled) {\n transform: scale(1.05)").concat(important, ";\n }\n\n .mobile-send-btn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n .mobile-input-hint {\n margin: 8px 0 0").concat(important, ";\n font-size: 11px").concat(important, ";\n color: #9ca3af").concat(important, ";\n text-align: center").concat(important, ";\n transition: color 0.2s ease").concat(important, ";\n }\n\n /* Mobile text input status states */\n .mobile-input-hint--sending {\n color: #666").concat(important, ";\n }\n\n .mobile-input-hint--success {\n color: #28a745").concat(important, ";\n }\n\n .mobile-input-hint--queued {\n color: #ffc107").concat(important, ";\n }\n\n .mobile-input-hint--error {\n color: #dc3545").concat(important, ";\n }\n\n /* Disabled mobile input styling */\n #mobileTextInput:disabled {\n background-color: #f5f5f5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n\n #mobileSendBtn:disabled {\n opacity: 0.5").concat(important, ";\n cursor: not-allowed").concat(important, ";\n }\n ");
|
|
36100
36357
|
}
|
|
36101
36358
|
|
|
36102
36359
|
/**
|
|
@@ -36123,7 +36380,10 @@ var Styles = /*#__PURE__*/function () {
|
|
|
36123
36380
|
"use strict";
|
|
36124
36381
|
__webpack_require__.r(__webpack_exports__);
|
|
36125
36382
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
36126
|
-
/* harmony export */ Templates: () => (/* binding */ Templates)
|
|
36383
|
+
/* harmony export */ Templates: () => (/* binding */ Templates),
|
|
36384
|
+
/* harmony export */ escapeHtmlAttr: () => (/* binding */ escapeHtmlAttr),
|
|
36385
|
+
/* harmony export */ resolveIdleHeaderAvatarUrl: () => (/* binding */ resolveIdleHeaderAvatarUrl),
|
|
36386
|
+
/* harmony export */ sanitizeHeaderAvatarImageUrl: () => (/* binding */ sanitizeHeaderAvatarImageUrl)
|
|
36127
36387
|
/* harmony export */ });
|
|
36128
36388
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
36129
36389
|
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
@@ -36145,6 +36405,37 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
36145
36405
|
* - None (stateless template generation)
|
|
36146
36406
|
*/
|
|
36147
36407
|
|
|
36408
|
+
/** Allow only http(s) absolute URLs for idle header avatar images. */
|
|
36409
|
+
function sanitizeHeaderAvatarImageUrl(raw) {
|
|
36410
|
+
var s = raw != null && String(raw).trim() || '';
|
|
36411
|
+
if (!s) return '';
|
|
36412
|
+
try {
|
|
36413
|
+
var u = new URL(s);
|
|
36414
|
+
if (u.protocol !== 'http:' && u.protocol !== 'https:') return '';
|
|
36415
|
+
return u.href;
|
|
36416
|
+
} catch (_unused) {
|
|
36417
|
+
return '';
|
|
36418
|
+
}
|
|
36419
|
+
}
|
|
36420
|
+
function escapeHtmlAttr(s) {
|
|
36421
|
+
return String(s).replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
36422
|
+
}
|
|
36423
|
+
|
|
36424
|
+
/**
|
|
36425
|
+
* Resolve idle header avatar URL from flat + nested voice config (and legacy / API aliases).
|
|
36426
|
+
* The idle UI shows the first letter of the agent name only when this returns ''.
|
|
36427
|
+
*/
|
|
36428
|
+
function resolveIdleHeaderAvatarUrl(config) {
|
|
36429
|
+
if (!config) return '';
|
|
36430
|
+
var v = config.voice || {};
|
|
36431
|
+
var candidates = [config.headerAvatarImageUrl, v.headerAvatarImageUrl, config.header_avatar_image_url, v.header_avatar_image_url, v.avatarImageUrl, config.avatarImageUrl, v.avatar_image_url, config.avatar_image_url];
|
|
36432
|
+
for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
|
|
36433
|
+
var raw = _candidates[_i];
|
|
36434
|
+
var u = sanitizeHeaderAvatarImageUrl(raw);
|
|
36435
|
+
if (u) return u;
|
|
36436
|
+
}
|
|
36437
|
+
return '';
|
|
36438
|
+
}
|
|
36148
36439
|
var Templates = /*#__PURE__*/function () {
|
|
36149
36440
|
function Templates(voiceInterface) {
|
|
36150
36441
|
_classCallCheck(this, Templates);
|
|
@@ -36196,12 +36487,17 @@ var Templates = /*#__PURE__*/function () {
|
|
|
36196
36487
|
}
|
|
36197
36488
|
|
|
36198
36489
|
// Desktop UI - new dark theme design
|
|
36199
|
-
|
|
36490
|
+
// Prefer explicit agent name over header.title so the pill can use a separate CTA (header.pillTitle + header.title).
|
|
36491
|
+
var agentName = this.config.agentName != null && String(this.config.agentName).trim() !== '' ? String(this.config.agentName).trim() : 'Sasha';
|
|
36200
36492
|
var agentRole = this.config.agentRole || 'AI Voice Assistant';
|
|
36201
36493
|
var headline = this.config.headline || this.config.startCallTitle || 'Hi there 👋';
|
|
36202
36494
|
var subline = this.config.subline || this.config.startCallSubtitle || 'Ask me anything — I respond instantly<br>in voice or text.';
|
|
36203
36495
|
var avatarInitial = agentName.charAt(0).toUpperCase();
|
|
36204
|
-
return "<div class=\"voice-interface\" id=\"voiceInterface\">\n <!-- Idle View -->\n <div id=\"voiceIdleState\">\n <div class=\"ttp-hero\">\n <div class=\"ttp-header\">\n <div class=\"ttp-agent\">\n <div class=\"ttp-avatar-wrap\">\n <div class=\"ttp-avatar\">".concat(avatarInitial, "</div>\n <div class=\"ttp-online-dot\"></div>\n </div>\n <div>\n <div class=\"ttp-agent-name\">").concat(agentName, "</div>\n <div class=\"ttp-agent-role\">").concat(agentRole, "</div>\n </div>\n </div>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseIdle\" aria-label=\"Close widget\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-headline\">").concat(headline, "</div>\n <div class=\"ttp-subline\">").concat(subline, "</div>\n </div>\n\n <div class=\"ttp-body\">\n <button type=\"button\" class=\"ttp-btn-primary\" id=\"startCallBtn\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"").concat(this.config.startCallButtonTextColor || 'white', "\" stroke-width=\"2\">\n <path d=\"M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8\"/>\n </svg>\n ").concat(this.getText('startCallButtonText', 'startCall') || 'Start Voice Call', "\n </button>\n <button type=\"button\" class=\"ttp-btn-secondary\" id=\"startTextBtn\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ").concat(this.config.sendMessageText || this.getText('sendMessageText', 'sendMessage') || 'Send a Message', "\n </button>\n ").concat((_this$config$whatsapp = this.config.whatsapp) !== null && _this$config$whatsapp !== void 0 && _this$config$whatsapp.number ? "\n <a class=\"ttp-btn-wa\" id=\"ttpWhatsAppBtn\"\n href=\"https://wa.me/".concat(this.config.whatsapp.number).concat(this.config.whatsapp.text ? '?text=' + encodeURIComponent(this.config.whatsapp.text) : '', "\"\n target=\"_blank\" rel=\"noopener\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"#25d366\">\n <path d=\"M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.655-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z\"/>\n </svg>\n WhatsApp\n </a>\n ") : '', "\n </div>\n </div>\n\n <!-- Active Call View -->\n <div id=\"voiceActiveState\" style=\"display: none;\">\n <!-- Full voice section (hidden when items/rooms are shown) -->\n <div class=\"desktop-voice-section\" id=\"desktopVoiceSection\">\n <div class=\"ttp-call-hero\">\n <div class=\"ttp-call-topbar\">\n <div class=\"ttp-rec\">\n <div class=\"ttp-rec-dot\"></div>\n <span class=\"ttp-timer\" id=\"desktopTimerText\">00:00</span>\n </div>\n <span class=\"ttp-call-label\">Voice call active</span>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseActive\" aria-label=\"Close widget\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ttp-orb-wrap\">\n <div class=\"ttp-orb-rings\">\n <div class=\"ttp-ring ttp-ring-1\"></div>\n <div class=\"ttp-ring ttp-ring-2\"></div>\n <div class=\"ttp-orb\" id=\"desktopMainWaveform\">\n <div class=\"ttp-wave\" id=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"ttp-listen-label\" id=\"desktopStatusText\">").concat(this.t('listening') || 'Listening to you...', "</div>\n </div>\n </div>\n\n <div class=\"ttp-controls\">\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopMuteBtn\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-end-btn\" id=\"desktopEndCallBtn\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopSpeakerBtn\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Compact voice section (shown when items/rooms are visible) -->\n <div class=\"compact-voice-section\" id=\"compactVoiceSection\" style=\"display: none;\">\n <div class=\"compact-left\">\n <div class=\"compact-avatar\" id=\"desktopAvatarCompact\">\n <div class=\"ttp-orb compact-orb\" id=\"desktopMainWaveformCompact\">\n <div class=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"compact-info\">\n <div class=\"compact-timer\" id=\"desktopTimerCompact\">\n <span class=\"ttp-rec-dot\"></span>\n <span id=\"compactTimerText\">00:00</span>\n </div>\n <div class=\"compact-status\" id=\"desktopStatusCompact\">\n <span id=\"compactStatusText\">").concat(this.t('listening') || 'Listening...', "</span>\n </div>\n </div>\n </div>\n <div class=\"compact-controls\">\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopMuteBtnCompact\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn danger\" id=\"desktopEndCallBtnCompact\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" style=\"overflow: visible;\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\" transform=\"rotate(135 12 12)\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopSpeakerBtnCompact\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Transcript -->\n <div class=\"ttp-transcript desktop-conversation-panel\" id=\"desktopConversationPanel\">\n <div class=\"ttp-transcript-hdr\" id=\"conversationHeader\">\n <span class=\"ttp-live-label\">Live</span>\n <span class=\"ttp-toggle-text\" id=\"conversationToggleText\">Show history</span>\n <div class=\"ttp-dots\">\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n </div>\n </div>\n <div class=\"live-transcript-collapsed\" id=\"liveTranscriptCollapsed\">\n <div class=\"ttp-transcript-text\" id=\"liveTextCollapsed\">\n ").concat(this.t('transcriptWillAppear') || 'Transcript will appear here...', "<span class=\"ttp-cursor\"></span>\n </div>\n </div>\n <div class=\"conversation-history\" id=\"conversationHistory\">\n <div class=\"conversation-messages\" id=\"conversationMessages\"></div>\n <div class=\"live-message-row\" id=\"liveMessageRow\" style=\"display: none;\">\n <div class=\"message-bubble\">\n <span class=\"live-badge\">Live</span>\n <span id=\"liveMessageText\"></span><span class=\"ttp-cursor\"></span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Type row -->\n <div class=\"ttp-type-row voice-text-input-area\">\n <input class=\"ttp-input\" type=\"text\" id=\"voiceTextInput\" placeholder=\"").concat(this.getText('inputPlaceholder', 'typeMessage') || 'Or type here…', "\" aria-label=\"Type a message\" />\n <button type=\"button\" class=\"ttp-send-btn\" id=\"voiceSendBtn\" aria-label=\"Send message\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>");
|
|
36496
|
+
var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
|
|
36497
|
+
var idleAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"ttp-avatar-img\" />") : avatarInitial;
|
|
36498
|
+
var idleAvatarClass = headerAvatarUrl ? 'ttp-avatar ttp-avatar--image' : 'ttp-avatar';
|
|
36499
|
+
var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
|
|
36500
|
+
return "<div class=\"voice-interface\" id=\"voiceInterface\">\n <!-- Idle View -->\n <div id=\"voiceIdleState\">\n <div class=\"ttp-hero\">\n <div class=\"ttp-header\">\n <div class=\"ttp-agent\">\n <div class=\"ttp-avatar-wrap\">\n <div class=\"".concat(idleAvatarClass, "\">").concat(idleAvatarInner, "</div>\n <div class=\"ttp-online-dot\"></div>\n </div>\n <div>\n <div class=\"ttp-agent-name\">").concat(agentName, "</div>\n <div class=\"ttp-agent-role\">").concat(agentRole, "</div>\n </div>\n </div>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseIdle\" aria-label=\"Close widget\">\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n <div class=\"ttp-headline\">").concat(headline, "</div>\n <div class=\"ttp-subline\">").concat(subline, "</div>\n </div>\n\n <div class=\"ttp-body\">\n <button type=\"button\" class=\"ttp-btn-primary\" id=\"startCallBtn\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"").concat(this.config.startCallButtonTextColor || 'white', "\" stroke-width=\"2\">\n <path d=\"M12 2a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V5a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2M12 19v3M8 22h8\"/>\n </svg>\n ").concat(this.getText('startCallButtonText', 'startCall') || 'Start Voice Call', "\n </button>\n <button type=\"button\" class=\"ttp-btn-secondary\" id=\"startTextBtn\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/>\n </svg>\n ").concat(this.config.sendMessageText || this.getText('sendMessageText', 'sendMessage') || 'Send a Message', "\n </button>\n ").concat((_this$config$whatsapp = this.config.whatsapp) !== null && _this$config$whatsapp !== void 0 && _this$config$whatsapp.number ? "\n <a class=\"ttp-btn-wa\" id=\"ttpWhatsAppBtn\"\n href=\"https://wa.me/".concat(this.config.whatsapp.number).concat(this.config.whatsapp.text ? '?text=' + encodeURIComponent(this.config.whatsapp.text) : '', "\"\n target=\"_blank\" rel=\"noopener\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"#25d366\">\n <path d=\"M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.655-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z\"/>\n </svg>\n WhatsApp\n </a>\n ") : '', "\n </div>\n </div>\n\n <!-- Active Call View -->\n <div id=\"voiceActiveState\" style=\"display: none;\">\n <!-- Full voice section (hidden when items/rooms are shown) -->\n <div class=\"desktop-voice-section\" id=\"desktopVoiceSection\">\n <div class=\"ttp-call-hero\">\n <div class=\"ttp-call-topbar\">\n <div class=\"ttp-rec\">\n <div class=\"ttp-rec-dot\"></div>\n <span class=\"ttp-timer\" id=\"desktopTimerText\">00:00</span>\n </div>\n <span class=\"ttp-call-label\">Voice call active</span>\n <button type=\"button\" class=\"ttp-close-btn\" id=\"ttpCloseActive\" aria-label=\"Close widget\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n </div>\n\n <div class=\"ttp-orb-wrap\">\n <div class=\"ttp-orb-rings\">\n <div class=\"ttp-ring ttp-ring-1\"></div>\n <div class=\"ttp-ring ttp-ring-2\"></div>\n <div class=\"ttp-orb\" id=\"desktopMainWaveform\">\n <div class=\"ttp-wave\" id=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"ttp-listen-label\" id=\"desktopStatusText\">").concat(this.t('listening') || 'Listening to you...', "</div>\n </div>\n </div>\n\n <div class=\"ttp-controls\">\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopMuteBtn\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-end-btn\" id=\"desktopEndCallBtn\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"ttp-ctrl-btn\" id=\"desktopSpeakerBtn\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Compact voice section (shown when items/rooms are visible) -->\n <div class=\"compact-voice-section\" id=\"compactVoiceSection\" style=\"display: none;\">\n <div class=\"compact-left\">\n <div class=\"compact-avatar\" id=\"desktopAvatarCompact\">\n <div class=\"ttp-orb compact-orb\" id=\"desktopMainWaveformCompact\">\n <div class=\"ttp-wave\"></div>\n </div>\n </div>\n <div class=\"compact-info\">\n <div class=\"compact-timer\" id=\"desktopTimerCompact\">\n <span class=\"ttp-rec-dot\"></span>\n <span id=\"compactTimerText\">00:00</span>\n </div>\n <div class=\"compact-status\" id=\"desktopStatusCompact\">\n <span id=\"compactStatusText\">").concat(this.t('listening') || 'Listening...', "</span>\n </div>\n </div>\n </div>\n <div class=\"compact-controls\">\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopMuteBtnCompact\" title=\"").concat(this.getTooltip('mute'), "\" aria-label=\"Mute microphone\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-mic-icon\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-mic-off-icon\" style=\"display: none; position: absolute;\">\n <path d=\"M12 1a3 3 0 0 1 3 3v7a3 3 0 0 1-6 0V4a3 3 0 0 1 3-3z\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn danger\" id=\"desktopEndCallBtnCompact\" title=\"").concat(this.getTooltip('endCall'), "\" aria-label=\"End call\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" style=\"overflow: visible;\">\n <path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.99 12 19.79 19.79 0 0 1 1.97 3.4 2 2 0 0 1 3.95 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z\" transform=\"rotate(135 12 12)\"/>\n </svg>\n </button>\n <button type=\"button\" class=\"compact-control-btn secondary\" id=\"desktopSpeakerBtnCompact\" title=\"").concat(this.getTooltip('speaker'), "\" aria-label=\"Toggle speaker\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" class=\"desktop-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"desktop-speaker-off-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" stroke=\"currentColor\" stroke-width=\"1.8\" fill=\"none\"/>\n <line x1=\"5\" y1=\"5\" x2=\"19\" y2=\"19\" stroke=\"#ef4444\" stroke-width=\"1.5\" stroke-linecap=\"round\" opacity=\"0.85\"/>\n </svg>\n </button>\n </div>\n </div>\n\n <!-- Transcript -->\n <div class=\"ttp-transcript desktop-conversation-panel\" id=\"desktopConversationPanel\" dir=\"").concat(textDir, "\">\n <div class=\"ttp-transcript-hdr\" id=\"conversationHeader\">\n <span class=\"ttp-live-label\">Live</span>\n <span class=\"ttp-toggle-text\" id=\"conversationToggleText\">Show history</span>\n <div class=\"ttp-dots\">\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n <div class=\"ttp-dot\"></div>\n </div>\n </div>\n <div class=\"live-transcript-collapsed\" id=\"liveTranscriptCollapsed\">\n <div class=\"ttp-transcript-text\" id=\"liveTextCollapsed\">\n ").concat(this.t('transcriptWillAppear') || 'Transcript will appear here...', "<span class=\"ttp-cursor\"></span>\n </div>\n </div>\n <div class=\"conversation-history\" id=\"conversationHistory\">\n <div class=\"conversation-messages\" id=\"conversationMessages\"></div>\n <div class=\"live-message-row\" id=\"liveMessageRow\" style=\"display: none;\">\n <div class=\"message-bubble\" dir=\"").concat(textDir, "\">\n <span class=\"live-badge\">Live</span>\n <span id=\"liveMessageText\"></span><span class=\"ttp-cursor\"></span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Type row -->\n <div class=\"ttp-type-row voice-text-input-area\">\n <input class=\"ttp-input\" type=\"text\" id=\"voiceTextInput\" dir=\"").concat(textDir, "\" placeholder=\"").concat(this.getText('inputPlaceholder', 'typeMessage') || 'Or type here…', "\" aria-label=\"Type a message\" />\n <button type=\"button\" class=\"ttp-send-btn\" id=\"voiceSendBtn\" aria-label=\"Send message\">\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"white\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>");
|
|
36205
36501
|
}
|
|
36206
36502
|
|
|
36207
36503
|
/**
|
|
@@ -36211,9 +36507,13 @@ var Templates = /*#__PURE__*/function () {
|
|
|
36211
36507
|
key: "generateMobileHTML",
|
|
36212
36508
|
value: function generateMobileHTML() {
|
|
36213
36509
|
// For mobile, idle state goes in widget, but active state will be appended to body
|
|
36214
|
-
|
|
36510
|
+
var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
|
|
36511
|
+
var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
|
|
36512
|
+
var mobileAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"voice-avatar-img\" />") : '🤖';
|
|
36513
|
+
var mobileAvatarClass = headerAvatarUrl ? 'voice-avatar voice-avatar--image' : 'voice-avatar';
|
|
36514
|
+
return "<div class=\"voice-interface mobile-voice-interface\" id=\"voiceInterface\" dir=\"".concat(textDir, "\">\n <!-- Before Call State (same as desktop) -->\n <div id=\"voiceIdleState\">\n <div class=\"").concat(mobileAvatarClass, "\" id=\"voiceAvatar\">").concat(mobileAvatarInner, "</div>\n <div class=\"voice-status\">\n <div class=\"voice-status-title\">").concat(this.getText('startCallTitle', 'clickToStartCall'), "</div>\n <div class=\"voice-status-subtitle\">").concat(this.getText('startCallSubtitle', 'realTimeVoice'), "</div>\n </div>\n <button type=\"button\" class=\"start-call-btn\" id=\"startCallBtn\">\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z\"/>\n </svg>\n <span>").concat(this.getText('startCallButtonText', 'startCall'), "</span>\n </button>\n </div>\n \n <!-- Mobile Active Call State - Hidden placeholder (actual bar will be appended to body) -->\n <div id=\"voiceActiveState\" class=\"mobile-active-state\" style=\"display: none;\">\n <!-- Duration Badge -->\n <div class=\"mobile-duration-badge\" id=\"mobileDurationBadge\">\n <div class=\"mobile-duration-dot\"></div>\n <span id=\"mobileDurationText\">00:00</span>\n </div>\n \n <!-- Main Bar -->\n <div class=\"mobile-voice-bar\">\n <!-- Top Row: Status, Waveform, Controls -->\n <div class=\"mobile-top-row\">\n <!-- Status Indicator -->\n <div class=\"mobile-status-indicator\">\n <div class=\"mobile-status-dot\" id=\"mobileStatusDot\"></div>\n <span class=\"mobile-status-text\" id=\"mobileStatusText\">Listening...</span>\n </div>\n \n <!-- Centered Waveform -->\n <div class=\"mobile-waveform-center\" id=\"mobileWaveform\">\n ").concat(Array(8).fill(0).map(function (_, i) {
|
|
36215
36515
|
return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
|
|
36216
|
-
}).join(''), "\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\"
|
|
36516
|
+
}).join(''), "\n </div>\n \n <!-- Controls -->\n <div class=\"mobile-controls\">\n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileMuteBtn\" aria-label=\"Mute microphone\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-icon\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-mic-off-icon\" style=\"display: none;\">\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/>\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-control-btn\" id=\"mobileSpeakerBtn\" aria-label=\"Toggle speaker\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-icon\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"mobile-speaker-off-icon\" style=\"display: none;\">\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n <line x1=\"4\" y1=\"4\" x2=\"20\" y2=\"20\" stroke=\"#ef4444\" stroke-width=\"1.5\" opacity=\"0.85\"/>\n </svg>\n </button>\n \n <button type=\"button\" class=\"mobile-end-call-btn\" id=\"mobileEndCallBtn\" aria-label=\"End call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91\"/>\n <line x1=\"22\" x2=\"2\" y1=\"2\" y2=\"22\"/>\n </svg>\n </button>\n </div>\n </div>\n \n <!-- Bottom Row: Transcript (expandable) -->\n <button type=\"button\" class=\"mobile-transcript-row\" id=\"mobileTranscriptRow\">\n <p class=\"mobile-transcript-text\" id=\"mobileTranscriptText\" dir=\"").concat(textDir, "\">").concat(this.t('transcriptWillAppear'), "</p>\n <div class=\"mobile-transcript-footer\">\n <span class=\"mobile-expand-hint\">tap to expand & type</span>\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" style=\"opacity: 0.6;\">\n <path d=\"M7 17L17 7M17 7H7M17 7V17\"/>\n </svg>\n </div>\n </button>\n </div>\n </div>\n \n <!-- Expanded Transcript Overlay -->\n <div class=\"mobile-transcript-overlay\" id=\"mobileTranscriptOverlay\">\n <div class=\"mobile-expanded-transcript\" id=\"mobileExpandedTranscript\">\n <!-- Header -->\n <div class=\"mobile-transcript-header\">\n <div class=\"mobile-header-left\">\n <div class=\"mobile-header-status\">\n <div class=\"mobile-header-status-dot\"></div>\n <span class=\"mobile-header-status-text\" id=\"mobileHeaderStatusText\">Listening...</span>\n <span class=\"mobile-header-duration\" id=\"mobileHeaderDuration\">00:00</span>\n </div>\n <span class=\"mobile-transcript-label\">CONVERSATION</span>\n </div>\n <button type=\"button\" class=\"mobile-close-transcript-btn\" id=\"mobileCloseTranscriptBtn\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n \n <!-- Messages Container -->\n <div class=\"mobile-messages-container\" id=\"mobileMessagesContainer\">\n <!-- Messages will be dynamically added here -->\n </div>\n \n <!-- Text Input Area -->\n <div class=\"mobile-input-area\">\n <div class=\"mobile-input-wrapper\">\n <input\n type=\"text\"\n placeholder=\"Type a message...\"\n id=\"mobileTextInput\"\n class=\"mobile-text-input\"\n dir=\"").concat(textDir, "\"\n />\n <button type=\"button\" class=\"mobile-send-btn\" id=\"mobileSendBtn\" disabled>\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z\"/>\n </svg>\n </button>\n </div>\n <p class=\"mobile-input-hint\">\uD83C\uDF99\uFE0F Voice is still active \u2022 Type or speak</p>\n </div>\n </div>\n </div>\n </div>");
|
|
36217
36517
|
}
|
|
36218
36518
|
}]);
|
|
36219
36519
|
}();
|
|
@@ -36979,10 +37279,11 @@ var Transcript = /*#__PURE__*/function () {
|
|
|
36979
37279
|
messagesToRender = messagesToRender.slice(0, -1);
|
|
36980
37280
|
}
|
|
36981
37281
|
}
|
|
37282
|
+
var textDir = this.config.direction === 'rtl' ? 'rtl' : 'ltr';
|
|
36982
37283
|
console.log('📝 [TRANSCRIPT] Rendering', messagesToRender.length, 'messages (live message excluded)');
|
|
36983
37284
|
container.innerHTML = messagesToRender.map(function (msg) {
|
|
36984
37285
|
var isUser = msg.role === 'user';
|
|
36985
|
-
return "\n <div class=\"message-row ".concat(msg.role, "\">\n <div class=\"message-avatar ").concat(msg.role, "\">\n ").concat(isUser ? 'U' : '<div class="orb"></div>', "\n </div>\n <div class=\"message-bubble\">").concat(_this.escapeHtml(msg.content), "</div>\n </div>\n ");
|
|
37286
|
+
return "\n <div class=\"message-row ".concat(msg.role, "\">\n <div class=\"message-avatar ").concat(msg.role, "\">\n ").concat(isUser ? 'U' : '<div class="orb"></div>', "\n </div>\n <div class=\"message-bubble\" dir=\"").concat(textDir, "\">").concat(_this.escapeHtml(msg.content), "</div>\n </div>\n ");
|
|
36986
37287
|
}).join('');
|
|
36987
37288
|
|
|
36988
37289
|
// Scroll to bottom
|
|
@@ -37020,10 +37321,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37020
37321
|
"startCall": "Start Call",
|
|
37021
37322
|
"connecting": "Connecting...",
|
|
37022
37323
|
"connectingSubtitle": "Please wait",
|
|
37324
|
+
"awaitingBrowserMic": "Waiting for microphone…",
|
|
37325
|
+
"awaitingBrowserMicDetail": "Allow access in your browser’s permission prompt.",
|
|
37023
37326
|
"listening": "Listening...",
|
|
37024
37327
|
"speakFreely": "Speak freely",
|
|
37025
37328
|
"liveTranscript": "Live Transcript",
|
|
37026
37329
|
"transcriptWillAppear": "Transcript will appear here during the call...",
|
|
37330
|
+
"userTranscriptPrefix": "You: ",
|
|
37027
37331
|
"mute": "Mute",
|
|
37028
37332
|
"speaker": "Speaker",
|
|
37029
37333
|
"endCall": "End Call",
|
|
@@ -37032,6 +37336,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37032
37336
|
"online": "Online",
|
|
37033
37337
|
"newChat": "New Chat",
|
|
37034
37338
|
"back": "Back",
|
|
37339
|
+
"backToModeChoice": "Voice or text",
|
|
37035
37340
|
"close": "Close",
|
|
37036
37341
|
"error": "Error",
|
|
37037
37342
|
"typeMessage": "Type your message...",
|
|
@@ -37049,10 +37354,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37049
37354
|
"startCall": "התחל שיחה",
|
|
37050
37355
|
"connecting": "מתחבר...",
|
|
37051
37356
|
"connectingSubtitle": "אנא המתן",
|
|
37357
|
+
"awaitingBrowserMic": "ממתין למיקרופון…",
|
|
37358
|
+
"awaitingBrowserMicDetail": "אשר גישה בחלון ההרשאות של הדפדפן.",
|
|
37052
37359
|
"listening": "מקשיב...",
|
|
37053
37360
|
"speakFreely": "דבר בחופשיות",
|
|
37054
37361
|
"liveTranscript": "תמלול בזמן אמת",
|
|
37055
37362
|
"transcriptWillAppear": "התמלול יופיע כאן במהלך השיחה...",
|
|
37363
|
+
"userTranscriptPrefix": "אתה: ",
|
|
37056
37364
|
"mute": "השתק",
|
|
37057
37365
|
"speaker": "רמקול",
|
|
37058
37366
|
"endCall": "סיים שיחה",
|
|
@@ -37061,6 +37369,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37061
37369
|
"online": "מקוון",
|
|
37062
37370
|
"newChat": "צ'אט חדש",
|
|
37063
37371
|
"back": "חזור",
|
|
37372
|
+
"backToModeChoice": "קול או טקסט",
|
|
37064
37373
|
"close": "סגור",
|
|
37065
37374
|
"error": "שגיאה",
|
|
37066
37375
|
"typeMessage": "הקלד הודעה...",
|
|
@@ -37078,10 +37387,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37078
37387
|
"startCall": "ابدأ المكالمة",
|
|
37079
37388
|
"connecting": "جارٍ الاتصال...",
|
|
37080
37389
|
"connectingSubtitle": "يرجى الانتظار",
|
|
37390
|
+
"awaitingBrowserMic": "في انتظار الميكروفون…",
|
|
37391
|
+
"awaitingBrowserMicDetail": "اسمح بالوصول في موجه أذونات المتصفح.",
|
|
37081
37392
|
"listening": "الاستماع...",
|
|
37082
37393
|
"speakFreely": "تكلم بحرية",
|
|
37083
37394
|
"liveTranscript": "نص مباشر",
|
|
37084
37395
|
"transcriptWillAppear": "سيظهر النص هنا أثناء المكالمة...",
|
|
37396
|
+
"userTranscriptPrefix": "أنت: ",
|
|
37085
37397
|
"mute": "كتم الصوت",
|
|
37086
37398
|
"speaker": "مكبر الصوت",
|
|
37087
37399
|
"endCall": "إنهاء المكالمة",
|
|
@@ -37090,6 +37402,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37090
37402
|
"online": "متصل",
|
|
37091
37403
|
"newChat": "محادثة جديدة",
|
|
37092
37404
|
"back": "رجوع",
|
|
37405
|
+
"backToModeChoice": "صوت أو نص",
|
|
37093
37406
|
"close": "إغلاق",
|
|
37094
37407
|
"error": "خطأ",
|
|
37095
37408
|
"typeMessage": "اكتب رسالة...",
|
|
@@ -37107,10 +37420,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37107
37420
|
"startCall": "Начать звонок",
|
|
37108
37421
|
"connecting": "Подключение...",
|
|
37109
37422
|
"connectingSubtitle": "Пожалуйста, подождите",
|
|
37423
|
+
"awaitingBrowserMic": "Ожидание микрофона…",
|
|
37424
|
+
"awaitingBrowserMicDetail": "Разрешите доступ в запросе браузера.",
|
|
37110
37425
|
"listening": "Слушаю...",
|
|
37111
37426
|
"speakFreely": "Говорите свободно",
|
|
37112
37427
|
"liveTranscript": "Живая транскрипция",
|
|
37113
37428
|
"transcriptWillAppear": "Транскрипция появится здесь во время звонка...",
|
|
37429
|
+
"userTranscriptPrefix": "Вы: ",
|
|
37114
37430
|
"mute": "Отключить звук",
|
|
37115
37431
|
"speaker": "Динамик",
|
|
37116
37432
|
"endCall": "Завершить звонок",
|
|
@@ -37119,6 +37435,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37119
37435
|
"online": "В сети",
|
|
37120
37436
|
"newChat": "Новый чат",
|
|
37121
37437
|
"back": "Назад",
|
|
37438
|
+
"backToModeChoice": "Голос или текст",
|
|
37122
37439
|
"close": "Закрыть",
|
|
37123
37440
|
"error": "Ошибка",
|
|
37124
37441
|
"typeMessage": "Введите сообщение...",
|
|
@@ -37136,10 +37453,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37136
37453
|
"startCall": "Iniciar llamada",
|
|
37137
37454
|
"connecting": "Conectando...",
|
|
37138
37455
|
"connectingSubtitle": "Por favor espere",
|
|
37456
|
+
"awaitingBrowserMic": "Esperando el micrófono…",
|
|
37457
|
+
"awaitingBrowserMicDetail": "Permita el acceso en el cuadro de permisos del navegador.",
|
|
37139
37458
|
"listening": "Escuchando...",
|
|
37140
37459
|
"speakFreely": "Habla libremente",
|
|
37141
37460
|
"liveTranscript": "Transcripción en vivo",
|
|
37142
37461
|
"transcriptWillAppear": "La transcripción aparecerá aquí durante la llamada...",
|
|
37462
|
+
"userTranscriptPrefix": "Tú: ",
|
|
37143
37463
|
"mute": "Silenciar",
|
|
37144
37464
|
"speaker": "Altavoz",
|
|
37145
37465
|
"endCall": "Terminar llamada",
|
|
@@ -37148,6 +37468,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37148
37468
|
"online": "En línea",
|
|
37149
37469
|
"newChat": "Nuevo chat",
|
|
37150
37470
|
"back": "Atrás",
|
|
37471
|
+
"backToModeChoice": "Voz o texto",
|
|
37151
37472
|
"close": "Cerrar",
|
|
37152
37473
|
"error": "Error",
|
|
37153
37474
|
"typeMessage": "Escribe un mensaje...",
|
|
@@ -37165,10 +37486,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37165
37486
|
"startCall": "Démarrer l'appel",
|
|
37166
37487
|
"connecting": "Connexion...",
|
|
37167
37488
|
"connectingSubtitle": "Veuillez patienter",
|
|
37489
|
+
"awaitingBrowserMic": "En attente du microphone…",
|
|
37490
|
+
"awaitingBrowserMicDetail": "Autorisez l’accès dans la fenêtre d’autorisation du navigateur.",
|
|
37168
37491
|
"listening": "Écoute...",
|
|
37169
37492
|
"speakFreely": "Parlez librement",
|
|
37170
37493
|
"liveTranscript": "Transcripción en direct",
|
|
37171
37494
|
"transcriptWillAppear": "La transcription apparaîtra ici pendant l'appel...",
|
|
37495
|
+
"userTranscriptPrefix": "Vous : ",
|
|
37172
37496
|
"mute": "Muet",
|
|
37173
37497
|
"speaker": "Haut-parleur",
|
|
37174
37498
|
"endCall": "Terminer l'appel",
|
|
@@ -37177,6 +37501,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37177
37501
|
"online": "En ligne",
|
|
37178
37502
|
"newChat": "Nouveau chat",
|
|
37179
37503
|
"back": "Retour",
|
|
37504
|
+
"backToModeChoice": "Voix ou texte",
|
|
37180
37505
|
"close": "Fermer",
|
|
37181
37506
|
"error": "Erreur",
|
|
37182
37507
|
"typeMessage": "Tapez votre message...",
|
|
@@ -37194,10 +37519,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37194
37519
|
"startCall": "Anruf starten",
|
|
37195
37520
|
"connecting": "Verbinden...",
|
|
37196
37521
|
"connectingSubtitle": "Bitte warten",
|
|
37522
|
+
"awaitingBrowserMic": "Warte auf Mikrofon…",
|
|
37523
|
+
"awaitingBrowserMicDetail": "Erlauben Sie den Zugriff in der Browser-Anfrage.",
|
|
37197
37524
|
"listening": "Hören...",
|
|
37198
37525
|
"speakFreely": "Sprechen Sie frei",
|
|
37199
37526
|
"liveTranscript": "Live-Transkription",
|
|
37200
37527
|
"transcriptWillAppear": "Die Transkription erscheint hier während des Anrufs...",
|
|
37528
|
+
"userTranscriptPrefix": "Sie: ",
|
|
37201
37529
|
"mute": "Stumm",
|
|
37202
37530
|
"speaker": "Lautsprecher",
|
|
37203
37531
|
"endCall": "Anruf beenden",
|
|
@@ -37206,6 +37534,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
37206
37534
|
"online": "Online",
|
|
37207
37535
|
"newChat": "Neuer Chat",
|
|
37208
37536
|
"back": "Zurück",
|
|
37537
|
+
"backToModeChoice": "Sprache oder Text",
|
|
37209
37538
|
"close": "Schließen",
|
|
37210
37539
|
"error": "Fehler",
|
|
37211
37540
|
"typeMessage": "Geben Sie eine Nachricht ein...",
|