ttp-agent-sdk 2.45.7 → 2.45.14
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 +1358 -379
- 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/index.html +1110 -127
- package/package.json +1 -1
package/dist/agent-widget.dev.js
CHANGED
|
@@ -10641,7 +10641,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
10641
10641
|
/* harmony export */ CLIENT_TOOLS_PARTNER_ID: () => (/* binding */ CLIENT_TOOLS_PARTNER_ID),
|
|
10642
10642
|
/* harmony export */ ClientScriptManager: () => (/* binding */ ClientScriptManager)
|
|
10643
10643
|
/* harmony export */ });
|
|
10644
|
-
/* harmony import */ var
|
|
10644
|
+
/* harmony import */ var _ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ClientToolsRegistry.js */ "./src/core/ClientToolsRegistry.js");
|
|
10645
|
+
/* harmony import */ var _ecommerce_PartnerScriptRunner_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../ecommerce/PartnerScriptRunner.js */ "./src/ecommerce/PartnerScriptRunner.js");
|
|
10645
10646
|
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); }
|
|
10646
10647
|
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; }
|
|
10647
10648
|
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; }
|
|
@@ -10688,11 +10689,10 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
10688
10689
|
*/
|
|
10689
10690
|
|
|
10690
10691
|
|
|
10692
|
+
|
|
10691
10693
|
/** Reserved partner id for the flavor-independent client-tool bundle. */
|
|
10692
10694
|
var CLIENT_TOOLS_PARTNER_ID = '__client_tools__';
|
|
10693
|
-
|
|
10694
|
-
/** Mirror of ClientToolsRegistry.MAX_RESULT_SIZE — 50KB cap on result payloads. */
|
|
10695
|
-
var MAX_RESULT_SIZE = 50000;
|
|
10695
|
+
var MAX_RESULT_SIZE = _ClientToolsRegistry_js__WEBPACK_IMPORTED_MODULE_0__["default"].MAX_RESULT_SIZE;
|
|
10696
10696
|
var LOG = '[ClientScriptManager]';
|
|
10697
10697
|
var ClientScriptManager = /*#__PURE__*/function () {
|
|
10698
10698
|
/**
|
|
@@ -10711,7 +10711,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
|
|
|
10711
10711
|
_classCallCheck(this, ClientScriptManager);
|
|
10712
10712
|
this._send = typeof send === 'function' ? send : function () {};
|
|
10713
10713
|
this._label = label;
|
|
10714
|
-
this.runner = new
|
|
10714
|
+
this.runner = new _ecommerce_PartnerScriptRunner_js__WEBPACK_IMPORTED_MODULE_1__.PartnerScriptRunner({
|
|
10715
10715
|
genericCtx: true
|
|
10716
10716
|
});
|
|
10717
10717
|
// Unsolicited adapter pushes (ctx.emit) go back over the same channel.
|
|
@@ -10735,7 +10735,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
|
|
|
10735
10735
|
* {@link isClientToolsToolCall}) against the client-tool runner and answer
|
|
10736
10736
|
* with the standard `client_tool_result` / `client_tool_error` envelopes —
|
|
10737
10737
|
* the exact shapes ClientToolsRegistry sends, since the backend awaits the
|
|
10738
|
-
* reply keyed by `toolCallId`. Enforces the
|
|
10738
|
+
* reply keyed by `toolCallId`. Enforces the result-size cap ({@link ClientToolsRegistry.MAX_RESULT_SIZE}).
|
|
10739
10739
|
*
|
|
10740
10740
|
* @param {object} message { toolCallId, toolName, parameters:{ action, args, partner_id } }
|
|
10741
10741
|
* @param {string|null} conversationId the SDK's current conversation id
|
|
@@ -10875,7 +10875,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
|
|
|
10875
10875
|
/**
|
|
10876
10876
|
* Execute a `run_partner_script` envelope against the client-tool runner and
|
|
10877
10877
|
* post the `run_partner_script_result` back over the channel. Enforces the
|
|
10878
|
-
*
|
|
10878
|
+
* result-size cap (mirror ClientToolsRegistry.MAX_RESULT_SIZE).
|
|
10879
10879
|
*
|
|
10880
10880
|
* An unknown action (e.g. bundle not yet received) resolves to ok:false with
|
|
10881
10881
|
* the runner's `adapter_not_in_bundle` reason — same behavior as the existing
|
|
@@ -10908,7 +10908,7 @@ var ClientScriptManager = /*#__PURE__*/function () {
|
|
|
10908
10908
|
case 3:
|
|
10909
10909
|
result = _context2.v;
|
|
10910
10910
|
elapsedMs = Date.now() - startedAt;
|
|
10911
|
-
ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; //
|
|
10911
|
+
ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; // Result-size cap (mirror ClientToolsRegistry.MAX_RESULT_SIZE).
|
|
10912
10912
|
serializedSize = 0;
|
|
10913
10913
|
try {
|
|
10914
10914
|
serializedSize = JSON.stringify(result).length;
|
|
@@ -11045,7 +11045,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
11045
11045
|
* the registered handler and sends back the result or error.
|
|
11046
11046
|
*/
|
|
11047
11047
|
var ClientToolsRegistry = /*#__PURE__*/function () {
|
|
11048
|
-
// 500KB
|
|
11048
|
+
// ~500KB cap on all client_tool_result payloads
|
|
11049
11049
|
|
|
11050
11050
|
function ClientToolsRegistry(sendMessage) {
|
|
11051
11051
|
var getConversationId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
|
|
@@ -11205,10 +11205,7 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
|
|
|
11205
11205
|
value: function sendResult(toolCallId, toolName, result, executionTimeMs) {
|
|
11206
11206
|
var conversationId = this.getConversationId();
|
|
11207
11207
|
var timestamp = new Date().toISOString();
|
|
11208
|
-
|
|
11209
|
-
// Size validation — images (base64) get a higher limit than text-only results
|
|
11210
|
-
var hasImage = result && _typeof(result) === 'object' && result.image && result.mimeType;
|
|
11211
|
-
var maxSize = hasImage ? ClientToolsRegistry.MAX_IMAGE_RESULT_SIZE : ClientToolsRegistry.MAX_RESULT_SIZE;
|
|
11208
|
+
var maxSize = ClientToolsRegistry.MAX_RESULT_SIZE;
|
|
11212
11209
|
var serializedSize = 0;
|
|
11213
11210
|
try {
|
|
11214
11211
|
serializedSize = JSON.stringify(result).length;
|
|
@@ -11218,7 +11215,9 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
|
|
|
11218
11215
|
if (serializedSize > maxSize) {
|
|
11219
11216
|
var sizeKB = Math.round(serializedSize / 1024);
|
|
11220
11217
|
var limitKB = Math.round(maxSize / 1024);
|
|
11221
|
-
|
|
11218
|
+
var productCount = result && Array.isArray(result.products) ? result.products.length : null;
|
|
11219
|
+
var detail = productCount != null ? " (".concat(productCount, " products in payload \u2014 trim search.api rows or raise cap)") : '';
|
|
11220
|
+
console.error("\uD83D\uDD27 ClientTools: Result for '".concat(toolName, "' exceeds size limit (").concat(sizeKB, "KB > ").concat(limitKB, "KB)").concat(detail), (result === null || result === void 0 ? void 0 : result.reason) || (result === null || result === void 0 ? void 0 : result.error) || '');
|
|
11222
11221
|
this.sendError(toolCallId, toolName, "Result too large: ".concat(sizeKB, "KB exceeds ").concat(limitKB, "KB limit"), 'RESULT_TOO_LARGE', executionTimeMs);
|
|
11223
11222
|
return;
|
|
11224
11223
|
}
|
|
@@ -11278,9 +11277,7 @@ var ClientToolsRegistry = /*#__PURE__*/function () {
|
|
|
11278
11277
|
}
|
|
11279
11278
|
}]);
|
|
11280
11279
|
}();
|
|
11281
|
-
_defineProperty(ClientToolsRegistry, "MAX_RESULT_SIZE",
|
|
11282
|
-
// 50KB for text-only results
|
|
11283
|
-
_defineProperty(ClientToolsRegistry, "MAX_IMAGE_RESULT_SIZE", 512000);
|
|
11280
|
+
_defineProperty(ClientToolsRegistry, "MAX_RESULT_SIZE", 512000);
|
|
11284
11281
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ClientToolsRegistry);
|
|
11285
11282
|
|
|
11286
11283
|
/***/ }),
|
|
@@ -11947,7 +11944,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
|
|
|
11947
11944
|
|
|
11948
11945
|
// SDK build time for debugging
|
|
11949
11946
|
if (true) {
|
|
11950
|
-
helloMessage.lastBuildTime = "2026-06-
|
|
11947
|
+
helloMessage.lastBuildTime = "2026-06-29T06:35:24.857Z";
|
|
11951
11948
|
}
|
|
11952
11949
|
try {
|
|
11953
11950
|
this.ws.send(JSON.stringify(helloMessage));
|
|
@@ -13564,6 +13561,7 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13564
13561
|
this.onTogglePause = opts.onTogglePause || function () {};
|
|
13565
13562
|
this.onToggleSpeaker = opts.onToggleSpeaker || function () {};
|
|
13566
13563
|
this.onSendText = opts.onSendText || function () {};
|
|
13564
|
+
this.onAbout = typeof opts.onAbout === 'function' ? opts.onAbout : null;
|
|
13567
13565
|
this._kbdOpen = false;
|
|
13568
13566
|
this._el = null;
|
|
13569
13567
|
this._build();
|
|
@@ -13651,11 +13649,8 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13651
13649
|
}, {
|
|
13652
13650
|
key: "_footerHtml",
|
|
13653
13651
|
value: function _footerHtml() {
|
|
13654
|
-
|
|
13655
|
-
|
|
13656
|
-
brandUrl = _this$footer.brandUrl,
|
|
13657
|
-
brandName = _this$footer.brandName;
|
|
13658
|
-
return "\n <div id=\"ttp-ecom-footer\" class=\"ttp-ecom-footer\">\n <span>Powered by <a href=\"".concat(brandUrl, "\" target=\"_blank\" rel=\"noopener noreferrer\"><b>").concat(brandName, "</b></a></span>\n </div>");
|
|
13652
|
+
var brand = this.footer ? "<span>Powered by <a href=\"".concat(this.footer.brandUrl, "\" target=\"_blank\" rel=\"noopener noreferrer\"><b>").concat(this.footer.brandName, "</b></a></span>") : '';
|
|
13653
|
+
return "\n <div id=\"ttp-ecom-footer\" class=\"ttp-ecom-footer\">\n ".concat(brand, "\n <button type=\"button\" class=\"ttp-ecom-info-btn\" id=\"ttp-ecom-btn-info\" title=\"About\" aria-label=\"About\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\n <line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"16\"/>\n <circle cx=\"12\" cy=\"7.7\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n </div>");
|
|
13659
13654
|
}
|
|
13660
13655
|
}, {
|
|
13661
13656
|
key: "_wireEvents",
|
|
@@ -13684,6 +13679,12 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13684
13679
|
return $('ttp-ecom-input').focus();
|
|
13685
13680
|
}, 50);
|
|
13686
13681
|
});
|
|
13682
|
+
var infoBtn = $('ttp-ecom-btn-info');
|
|
13683
|
+
if (infoBtn) {
|
|
13684
|
+
infoBtn.addEventListener('click', function () {
|
|
13685
|
+
if (_this.onAbout) _this.onAbout();
|
|
13686
|
+
});
|
|
13687
|
+
}
|
|
13687
13688
|
$('ttp-ecom-btn-end').addEventListener('click', function () {
|
|
13688
13689
|
return _this.onHangup();
|
|
13689
13690
|
});
|
|
@@ -13703,11 +13704,16 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13703
13704
|
}, {
|
|
13704
13705
|
key: "show",
|
|
13705
13706
|
value: function show() {
|
|
13707
|
+
var _this2 = this;
|
|
13706
13708
|
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
13707
13709
|
if (!this._el) return;
|
|
13708
13710
|
if (opts.reset !== false) this._reset();
|
|
13709
13711
|
this._el.style.display = '';
|
|
13710
13712
|
this.syncFromVoice();
|
|
13713
|
+
// Now that the strip has real dimensions, clamp any restored drag position.
|
|
13714
|
+
if (this._dragEnabled) requestAnimationFrame(function () {
|
|
13715
|
+
return _this2.reclampDrag();
|
|
13716
|
+
});
|
|
13711
13717
|
}
|
|
13712
13718
|
}, {
|
|
13713
13719
|
key: "hide",
|
|
@@ -13839,6 +13845,177 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13839
13845
|
if (!this.getVoiceUiState) return;
|
|
13840
13846
|
this.syncFromVoice();
|
|
13841
13847
|
}
|
|
13848
|
+
|
|
13849
|
+
/**
|
|
13850
|
+
* Make the strip draggable by its body. The wrapper is centered with
|
|
13851
|
+
* `translateX(-50%)`; a drag offset is layered on top of that. Control buttons
|
|
13852
|
+
* and the text input don't start a drag. Position is clamped to the viewport
|
|
13853
|
+
* (re-clamped on show/resize) and optionally persisted under `storageKey`.
|
|
13854
|
+
*
|
|
13855
|
+
* @param {Object} opts
|
|
13856
|
+
* @param {boolean} [opts.persist=true]
|
|
13857
|
+
* @param {string} [opts.storageKey]
|
|
13858
|
+
*/
|
|
13859
|
+
}, {
|
|
13860
|
+
key: "enableDrag",
|
|
13861
|
+
value: function enableDrag() {
|
|
13862
|
+
var _this3 = this;
|
|
13863
|
+
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
13864
|
+
if (!this._el || this._dragEnabled) return;
|
|
13865
|
+
var wrapper = this._el; // fixed, centered via translateX(-50%)
|
|
13866
|
+
var handle = wrapper.querySelector('#ttp-ecom-strip');
|
|
13867
|
+
if (!handle) return;
|
|
13868
|
+
this._dragEnabled = true;
|
|
13869
|
+
this._dragPersist = opts.persist !== false;
|
|
13870
|
+
this._dragKey = opts.storageKey || '';
|
|
13871
|
+
this._dragOffset = {
|
|
13872
|
+
x: 0,
|
|
13873
|
+
y: 0
|
|
13874
|
+
};
|
|
13875
|
+
handle.style.setProperty('cursor', 'move');
|
|
13876
|
+
handle.style.setProperty('touch-action', 'none');
|
|
13877
|
+
var EXCLUDE = 'button, a, input, textarea, select, [contenteditable]';
|
|
13878
|
+
var THRESHOLD = 5;
|
|
13879
|
+
var startX = 0,
|
|
13880
|
+
startY = 0,
|
|
13881
|
+
baseX = 0,
|
|
13882
|
+
baseY = 0,
|
|
13883
|
+
baseRect = null;
|
|
13884
|
+
var dragging = false,
|
|
13885
|
+
moved = false;
|
|
13886
|
+
var onMove = function onMove(e) {
|
|
13887
|
+
var dx = e.clientX - startX,
|
|
13888
|
+
dy = e.clientY - startY;
|
|
13889
|
+
if (!moved && Math.hypot(dx, dy) < THRESHOLD) return;
|
|
13890
|
+
moved = true;
|
|
13891
|
+
_this3._dragOffset = _this3._clampDragOffset(baseX + dx, baseY + dy, baseRect);
|
|
13892
|
+
_this3._applyDragOffset();
|
|
13893
|
+
};
|
|
13894
|
+
var _onUp = function onUp(e) {
|
|
13895
|
+
window.removeEventListener('pointermove', onMove);
|
|
13896
|
+
window.removeEventListener('pointerup', _onUp);
|
|
13897
|
+
handle.style.setProperty('cursor', 'move');
|
|
13898
|
+
try {
|
|
13899
|
+
handle.releasePointerCapture(e.pointerId);
|
|
13900
|
+
} catch (err) {/* not captured */}
|
|
13901
|
+
dragging = false;
|
|
13902
|
+
if (moved && _this3._dragPersist && _this3._dragKey) {
|
|
13903
|
+
try {
|
|
13904
|
+
window.localStorage.setItem(_this3._dragKey, JSON.stringify(_this3._dragOffset));
|
|
13905
|
+
} catch (err) {/* unavailable */}
|
|
13906
|
+
}
|
|
13907
|
+
};
|
|
13908
|
+
var onDown = function onDown(e) {
|
|
13909
|
+
if (e.button != null && e.button !== 0) return; // primary / touch / pen only
|
|
13910
|
+
if (dragging) return;
|
|
13911
|
+
if (e.target && e.target.closest && e.target.closest(EXCLUDE)) return;
|
|
13912
|
+
dragging = true;
|
|
13913
|
+
moved = false;
|
|
13914
|
+
startX = e.clientX;
|
|
13915
|
+
startY = e.clientY;
|
|
13916
|
+
baseX = _this3._dragOffset.x;
|
|
13917
|
+
baseY = _this3._dragOffset.y;
|
|
13918
|
+
baseRect = _this3._dragBaseRect();
|
|
13919
|
+
handle.style.setProperty('cursor', 'grabbing');
|
|
13920
|
+
try {
|
|
13921
|
+
handle.setPointerCapture(e.pointerId);
|
|
13922
|
+
} catch (err) {/* unsupported */}
|
|
13923
|
+
window.addEventListener('pointermove', onMove);
|
|
13924
|
+
window.addEventListener('pointerup', _onUp);
|
|
13925
|
+
};
|
|
13926
|
+
handle.addEventListener('pointerdown', onDown);
|
|
13927
|
+
|
|
13928
|
+
// Restore saved offset (unclamped here — the strip is hidden until show(),
|
|
13929
|
+
// where it gets clamped against real dimensions).
|
|
13930
|
+
if (this._dragPersist && this._dragKey) {
|
|
13931
|
+
try {
|
|
13932
|
+
var saved = JSON.parse(window.localStorage.getItem(this._dragKey) || 'null');
|
|
13933
|
+
if (saved && typeof saved.x === 'number' && typeof saved.y === 'number') {
|
|
13934
|
+
this._dragOffset = {
|
|
13935
|
+
x: saved.x,
|
|
13936
|
+
y: saved.y
|
|
13937
|
+
};
|
|
13938
|
+
this._applyDragOffset();
|
|
13939
|
+
}
|
|
13940
|
+
} catch (err) {/* ignore corrupt storage */}
|
|
13941
|
+
}
|
|
13942
|
+
}
|
|
13943
|
+
|
|
13944
|
+
/**
|
|
13945
|
+
* Base (offset-0) viewport rect used for clamping. Measures the *visible* inner
|
|
13946
|
+
* strip (`#ttp-ecom-strip`), not the wrapper: the wrapper is fixed at `bottom:0`
|
|
13947
|
+
* with bottom padding (incl. safe-area inset), so its bottom edge hugs the
|
|
13948
|
+
* viewport bottom and would wrongly forbid any downward drag. The drag offset is
|
|
13949
|
+
* applied to the wrapper, but both elements move together by the same amount, so
|
|
13950
|
+
* the inner strip's offset-0 rect is just its current rect minus the offset.
|
|
13951
|
+
*/
|
|
13952
|
+
}, {
|
|
13953
|
+
key: "_dragBaseRect",
|
|
13954
|
+
value: function _dragBaseRect() {
|
|
13955
|
+
var o = this._dragOffset || {
|
|
13956
|
+
x: 0,
|
|
13957
|
+
y: 0
|
|
13958
|
+
};
|
|
13959
|
+
var inner = this._el && this._el.querySelector('#ttp-ecom-strip') || this._el;
|
|
13960
|
+
var r = inner.getBoundingClientRect();
|
|
13961
|
+
return {
|
|
13962
|
+
left: r.left - o.x,
|
|
13963
|
+
top: r.top - o.y,
|
|
13964
|
+
right: r.right - o.x,
|
|
13965
|
+
bottom: r.bottom - o.y
|
|
13966
|
+
};
|
|
13967
|
+
}
|
|
13968
|
+
|
|
13969
|
+
/**
|
|
13970
|
+
* Clamp a drag offset so the strip stays within the viewport. An 8px margin is
|
|
13971
|
+
* kept on the top/left/right edges. The bottom is allowed to drag *past* the
|
|
13972
|
+
* viewport edge so the strip can be tucked partly off-screen — but at least
|
|
13973
|
+
* `MIN_VISIBLE` (10px) of its top stays on screen so it can always be grabbed
|
|
13974
|
+
* and dragged back up.
|
|
13975
|
+
*/
|
|
13976
|
+
}, {
|
|
13977
|
+
key: "_clampDragOffset",
|
|
13978
|
+
value: function _clampDragOffset(x, y, base) {
|
|
13979
|
+
if (!base) return {
|
|
13980
|
+
x: x,
|
|
13981
|
+
y: y
|
|
13982
|
+
};
|
|
13983
|
+
var margin = 8;
|
|
13984
|
+
var MIN_VISIBLE = 10;
|
|
13985
|
+
var minX = margin - base.left,
|
|
13986
|
+
maxX = window.innerWidth - margin - base.right;
|
|
13987
|
+
var minY = margin - base.top,
|
|
13988
|
+
maxY = window.innerHeight - MIN_VISIBLE - base.top;
|
|
13989
|
+
if (minX > maxX) maxX = minX;
|
|
13990
|
+
if (minY > maxY) maxY = minY;
|
|
13991
|
+
return {
|
|
13992
|
+
x: Math.min(Math.max(x, minX), maxX),
|
|
13993
|
+
y: Math.min(Math.max(y, minY), maxY)
|
|
13994
|
+
};
|
|
13995
|
+
}
|
|
13996
|
+
|
|
13997
|
+
/** Apply the drag offset on top of the centering transform. */
|
|
13998
|
+
}, {
|
|
13999
|
+
key: "_applyDragOffset",
|
|
14000
|
+
value: function _applyDragOffset() {
|
|
14001
|
+
if (!this._el) return;
|
|
14002
|
+
var o = this._dragOffset || {
|
|
14003
|
+
x: 0,
|
|
14004
|
+
y: 0
|
|
14005
|
+
};
|
|
14006
|
+
this._el.style.setProperty('transform', "translateX(-50%) translate(".concat(o.x, "px, ").concat(o.y, "px)"), 'important');
|
|
14007
|
+
}
|
|
14008
|
+
|
|
14009
|
+
/** Re-clamp the dragged strip to the current viewport (on show / resize). */
|
|
14010
|
+
}, {
|
|
14011
|
+
key: "reclampDrag",
|
|
14012
|
+
value: function reclampDrag() {
|
|
14013
|
+
if (!this._dragEnabled || !this._el) return;
|
|
14014
|
+
var r = this._el.getBoundingClientRect();
|
|
14015
|
+
if (!r.width && !r.height) return; // hidden — nothing to clamp yet
|
|
14016
|
+
this._dragOffset = this._clampDragOffset(this._dragOffset.x, this._dragOffset.y, this._dragBaseRect());
|
|
14017
|
+
this._applyDragOffset();
|
|
14018
|
+
}
|
|
13842
14019
|
}, {
|
|
13843
14020
|
key: "destroy",
|
|
13844
14021
|
value: function destroy() {
|
|
@@ -13850,12 +14027,12 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13850
14027
|
}, {
|
|
13851
14028
|
key: "_reset",
|
|
13852
14029
|
value: function _reset() {
|
|
13853
|
-
var
|
|
14030
|
+
var _this4 = this,
|
|
13854
14031
|
_$,
|
|
13855
14032
|
_$2;
|
|
13856
14033
|
this._kbdOpen = false;
|
|
13857
14034
|
var $ = function $(id) {
|
|
13858
|
-
return
|
|
14035
|
+
return _this4._el.querySelector('#' + id);
|
|
13859
14036
|
};
|
|
13860
14037
|
var tx = $('ttp-ecom-transcript');
|
|
13861
14038
|
if (tx) {
|
|
@@ -13898,7 +14075,7 @@ var EcommerceVoiceStrip = /*#__PURE__*/function () {
|
|
|
13898
14075
|
}
|
|
13899
14076
|
}]);
|
|
13900
14077
|
}();
|
|
13901
|
-
EcommerceVoiceStrip._CSS = "\n#ttp-ecom-strip-wrapper {\n position: fixed;\n left: 50%;\n bottom: 0;\n transform: translateX(-50%);\n width: min(720px, calc(100vw - 40px));\n max-width: calc(100vw - 40px);\n z-index: 2147483647;\n box-sizing: border-box;\n padding: 0 14px max(14px, env(safe-area-inset-bottom, 0px));\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n font-feature-settings: \"kern\" 1, \"liga\" 1;\n pointer-events: none;\n}\n#ttp-ecom-strip-wrapper * { box-sizing: border-box; }\n\n/* Layered glass dock: rim light, soft lift, optional backdrop tint */\n#ttp-ecom-strip {\n pointer-events: auto;\n position: relative;\n isolation: isolate;\n margin: 0;\n border-radius: 26px;\n border: 1px solid rgba(255, 255, 255, 0.18);\n background: var(--ecom-strip-bg, linear-gradient(145deg, #5b21b6 0%, #3730a3 42%, #1e1b4b 100%));\n background-clip: padding-box;\n color: var(--ecom-fg, #ffffff);\n box-shadow:\n 0 0 0 1px rgba(0, 0, 0, 0.18) inset,\n 0 1px 0 rgba(255, 255, 255, 0.14) inset,\n 0 -20px 40px -8px rgba(0, 0, 0, 0.22) inset,\n 0 12px 32px rgba(0, 0, 0, 0.22),\n 0 28px 56px -16px rgba(0, 0, 0, 0.45),\n 0 0 80px -20px rgba(99, 102, 241, 0.35);\n overflow: visible;\n}\n\n#ttp-ecom-strip::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 0;\n background: linear-gradient(\n 165deg,\n rgba(255, 255, 255, 0.08) 0%,\n rgba(255, 255, 255, 0) 42%,\n rgba(0, 0, 0, 0.12) 100%\n );\n}\n\n/* LIVE chip \u2014 glass capsule (backdrop blur), straddles top edge */\n#ttp-ecom-live-edge {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n z-index: 4;\n max-width: calc(100% - 52px);\n pointer-events: none;\n padding: 3px 14px 4px;\n border-radius: 999px;\n background: rgba(8, 6, 24, 0.78);\n border: 1px solid rgba(255, 255, 255, 0.28);\n box-shadow:\n 0 0 0 1px rgba(0, 0, 0, 0.35),\n 0 4px 16px rgba(0, 0, 0, 0.35),\n inset 0 1px 0 rgba(255, 255, 255, 0.12);\n}\n@supports (backdrop-filter: blur(1px)) {\n #ttp-ecom-live-edge {\n backdrop-filter: blur(14px) saturate(180%);\n -webkit-backdrop-filter: blur(14px) saturate(180%);\n }\n}\n\n#ttp-ecom-main-row {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 18px 16px 12px;\n min-height: 48px;\n}\n\n#ttp-ecom-footer {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 16px 10px;\n margin-top: -4px;\n border-top: 1px solid rgba(255, 255, 255, 0.06);\n padding-top: 6px;\n}\n#ttp-ecom-footer span {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.35);\n white-space: nowrap;\n}\n#ttp-ecom-footer a {\n color: rgba(167, 139, 250, 0.95);\n text-decoration: none;\n font-weight: 600;\n}\n#ttp-ecom-footer a:hover { opacity: 0.85; }\n#ttp-ecom-footer a b { font-weight: 700; }\n\n#ttp-ecom-left-controls,\n#ttp-ecom-right-cluster {\n display: flex;\n align-items: center;\n gap: 7px;\n flex-shrink: 0;\n}\n\n/* Inset \u201Cmeter bridge\u201D for transcript \u2014 keeps one-line layout, adds depth */\n#ttp-ecom-center {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n text-align: start;\n padding: 7px 12px 7px 14px;\n border-radius: 16px;\n background: rgba(0, 0, 0, 0.16);\n border: 1px solid rgba(255, 255, 255, 0.08);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.07),\n inset 0 -1px 0 rgba(0, 0, 0, 0.12);\n}\n\n#ttp-ecom-live-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-width: 0;\n}\n\n#ttp-ecom-live-label {\n font-size: 9px;\n font-weight: 800;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ecom-accent, #4ade80);\n opacity: 0.98;\n white-space: nowrap;\n}\n\n#ttp-ecom-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ecom-accent, #4ade80);\n flex-shrink: 0;\n box-shadow: 0 0 14px rgba(74, 222, 128, 0.45);\n animation: ttp-ecom-blink 1.35s ease-in-out infinite;\n}\n#ttp-ecom-dot.paused {\n animation: none;\n opacity: 0.45;\n background: rgba(255,255,255,0.35);\n box-shadow: none;\n}\n@keyframes ttp-ecom-blink {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.25; transform: scale(0.92); }\n}\n\n#ttp-ecom-transcript {\n font-size: 12px;\n line-height: 1.42;\n letter-spacing: 0.015em;\n color: rgba(255, 255, 255, 0.94);\n width: 100%;\n max-width: 100%;\n overflow: hidden;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n}\n\n#ttp-ecom-transcript.ttp-ecom-transcript--user {\n color: rgba(255, 244, 214, 0.98);\n font-weight: 600;\n letter-spacing: 0.02em;\n text-shadow: 0 0 28px rgba(251, 191, 36, 0.22);\n}\n\n/* Squircle glass controls */\n#ttp-ecom-strip .ttp-ecom-ctrl {\n width: 36px;\n height: 36px;\n border-radius: 12px;\n border: 1px solid rgba(255, 255, 255, 0.16);\n background: linear-gradient(165deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.05) 100%);\n color: rgba(255, 255, 255, 0.92);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n position: relative;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.18),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.14s ease;\n outline: none;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl:hover {\n background: linear-gradient(165deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.08) 100%);\n border-color: rgba(255, 255, 255, 0.32);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.22),\n 0 4px 14px rgba(0, 0, 0, 0.2);\n}\n#ttp-ecom-strip .ttp-ecom-ctrl:active { transform: scale(0.94); }\n#ttp-ecom-strip .ttp-ecom-ctrl:focus-visible {\n outline: 2px solid rgba(165, 180, 252, 0.95);\n outline-offset: 2px;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-active {\n background: linear-gradient(165deg, rgba(129, 140, 248, 0.45) 0%, rgba(99, 102, 241, 0.28) 100%) !important;\n border-color: rgba(196, 181, 253, 0.65) !important;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 0 1px rgba(99, 102, 241, 0.35),\n 0 6px 18px rgba(79, 70, 229, 0.35) !important;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-warn {\n background: linear-gradient(165deg, rgba(252, 165, 165, 0.22) 0%, rgba(239, 68, 68, 0.2) 100%) !important;\n border-color: rgba(252, 165, 165, 0.55) !important;\n}\n\n#ttp-ecom-strip .ttp-ecom-ctrl-end {\n width: 40px;\n height: 40px;\n border-radius: 14px;\n background: linear-gradient(165deg, #fb7185 0%, var(--ecom-end, #ef4444) 52%, #991b1b 100%) !important;\n border: none !important;\n color: #fff !important;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.25),\n 0 0 0 2px rgba(0, 0, 0, 0.12),\n 0 6px 22px rgba(239, 68, 68, 0.48);\n transform: rotate(135deg);\n transition: filter 0.18s ease, transform 0.14s ease, box-shadow 0.2s ease;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-end:hover {\n filter: brightness(1.06);\n transform: rotate(135deg) scale(1.05);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.28),\n 0 0 0 2px rgba(0, 0, 0, 0.12),\n 0 10px 28px rgba(239, 68, 68, 0.52);\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-end:active {\n transform: rotate(135deg) scale(0.94);\n}\n\n/* Mini waveform */\n#ttp-ecom-strip .ttp-ecom-mini-wave {\n display: flex;\n align-items: center;\n gap: 3px;\n height: 24px;\n padding: 0 4px;\n opacity: 0.9;\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb {\n width: 3px;\n border-radius: 3px;\n background: linear-gradient(180deg, #ddd6fe 0%, var(--ecom-accent, #a78bfa) 100%);\n animation: ttp-ecom-wa 0.78s ease-in-out infinite;\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(1) { height: 6px; animation-delay: 0s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(2) { height: 11px; animation-delay: 0.1s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(3) { height: 16px; animation-delay: 0.2s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(4) { height: 9px; animation-delay: 0.15s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(5) { height: 12px; animation-delay: 0.05s; }\n@keyframes ttp-ecom-wa {\n 0%, 100% { transform: scaleY(0.38); opacity: 0.5; }\n 50% { transform: scaleY(1); opacity: 1; }\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb.paused {\n animation-play-state: paused;\n transform: scaleY(0.32);\n opacity: 0.28;\n}\n\n/* Input row */\n#ttp-ecom-input-row {\n display: none;\n position: relative;\n z-index: 1;\n align-items: center;\n gap: 10px;\n padding: 0 14px 12px;\n margin-top: -2px;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n#ttp-ecom-input-row.open {\n display: flex;\n}\n#ttp-ecom-input {\n flex: 1;\n height: 40px;\n border-radius: 12px;\n border: 1px solid rgba(255, 255, 255, 0.18);\n background: rgba(0, 0, 0, 0.22);\n color: #fff;\n font-size: 14px;\n padding: 0 14px;\n outline: none;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);\n transition: border-color 0.18s ease, box-shadow 0.18s ease;\n}\n#ttp-ecom-input::placeholder { color: rgba(255, 255, 255, 0.42); }\n#ttp-ecom-input:focus {\n border-color: rgba(165, 180, 252, 0.65);\n box-shadow:\n inset 0 1px 2px rgba(0, 0, 0, 0.2),\n 0 0 0 3px rgba(99, 102, 241, 0.25);\n}\n\n#ttp-ecom-strip .ttp-ecom-send {\n width: 36px;\n height: 36px;\n border-radius: 12px;\n border: none;\n background: linear-gradient(165deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.1) 100%);\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transition: background 0.18s ease, transform 0.12s ease;\n}\n#ttp-ecom-strip .ttp-ecom-send:hover {\n background: linear-gradient(165deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.14) 100%);\n}\n#ttp-ecom-strip .ttp-ecom-send:active { transform: scale(0.94); }\n\n@media (max-width: 520px) {\n #ttp-ecom-strip .ttp-ecom-mini-wave { display: none; }\n #ttp-ecom-main-row { gap: 7px; padding: 16px 12px 10px; }\n #ttp-ecom-strip .ttp-ecom-ctrl { width: 36px; height: 36px; }\n #ttp-ecom-strip .ttp-ecom-ctrl-end { width: 40px; height: 40px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n #ttp-ecom-dot { animation: none; opacity: 0.9; }\n #ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb { animation: none; opacity: 0.65; }\n}\n";
|
|
14078
|
+
EcommerceVoiceStrip._CSS = "\n#ttp-ecom-strip-wrapper {\n position: fixed;\n left: 50%;\n bottom: 0;\n transform: translateX(-50%);\n width: min(720px, calc(100vw - 40px));\n max-width: calc(100vw - 40px);\n z-index: 2147483647;\n box-sizing: border-box;\n padding: 0 14px max(14px, env(safe-area-inset-bottom, 0px));\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n font-feature-settings: \"kern\" 1, \"liga\" 1;\n pointer-events: none;\n}\n#ttp-ecom-strip-wrapper * { box-sizing: border-box; }\n\n/* Layered glass dock: rim light, soft lift, optional backdrop tint */\n#ttp-ecom-strip {\n pointer-events: auto;\n position: relative;\n isolation: isolate;\n margin: 0;\n border-radius: 26px;\n border: 1px solid rgba(255, 255, 255, 0.18);\n background: var(--ecom-strip-bg, linear-gradient(145deg, #5b21b6 0%, #3730a3 42%, #1e1b4b 100%));\n background-clip: padding-box;\n color: var(--ecom-fg, #ffffff);\n box-shadow:\n 0 0 0 1px rgba(0, 0, 0, 0.18) inset,\n 0 1px 0 rgba(255, 255, 255, 0.14) inset,\n 0 -20px 40px -8px rgba(0, 0, 0, 0.22) inset,\n 0 12px 32px rgba(0, 0, 0, 0.22),\n 0 28px 56px -16px rgba(0, 0, 0, 0.45),\n 0 0 80px -20px rgba(99, 102, 241, 0.35);\n overflow: visible;\n}\n\n#ttp-ecom-strip::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 0;\n background: linear-gradient(\n 165deg,\n rgba(255, 255, 255, 0.08) 0%,\n rgba(255, 255, 255, 0) 42%,\n rgba(0, 0, 0, 0.12) 100%\n );\n}\n\n/* LIVE chip \u2014 glass capsule (backdrop blur), straddles top edge */\n#ttp-ecom-live-edge {\n position: absolute;\n left: 50%;\n top: 0;\n transform: translate(-50%, -50%);\n z-index: 4;\n max-width: calc(100% - 52px);\n pointer-events: none;\n padding: 3px 14px 4px;\n border-radius: 999px;\n background: rgba(8, 6, 24, 0.78);\n border: 1px solid rgba(255, 255, 255, 0.28);\n box-shadow:\n 0 0 0 1px rgba(0, 0, 0, 0.35),\n 0 4px 16px rgba(0, 0, 0, 0.35),\n inset 0 1px 0 rgba(255, 255, 255, 0.12);\n}\n@supports (backdrop-filter: blur(1px)) {\n #ttp-ecom-live-edge {\n backdrop-filter: blur(14px) saturate(180%);\n -webkit-backdrop-filter: blur(14px) saturate(180%);\n }\n}\n\n#ttp-ecom-main-row {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 18px 16px 12px;\n min-height: 48px;\n}\n\n#ttp-ecom-footer {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 0 16px 10px;\n margin-top: -4px;\n border-top: 1px solid rgba(255, 255, 255, 0.06);\n padding-top: 6px;\n}\n.ttp-ecom-info-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px;\n margin: 0;\n background: none;\n border: none;\n cursor: pointer;\n line-height: 0;\n border-radius: 50%;\n color: rgba(255, 255, 255, 0.35);\n transition: color 0.2s, background 0.2s;\n}\n.ttp-ecom-info-btn:hover {\n color: rgba(255, 255, 255, 0.7);\n background: rgba(255, 255, 255, 0.08);\n}\n.ttp-ecom-info-btn svg { display: block; }\n#ttp-ecom-footer span {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.35);\n white-space: nowrap;\n}\n#ttp-ecom-footer a {\n color: rgba(167, 139, 250, 0.95);\n text-decoration: none;\n font-weight: 600;\n}\n#ttp-ecom-footer a:hover { opacity: 0.85; }\n#ttp-ecom-footer a b { font-weight: 700; }\n\n#ttp-ecom-left-controls,\n#ttp-ecom-right-cluster {\n display: flex;\n align-items: center;\n gap: 7px;\n flex-shrink: 0;\n}\n\n/* Inset \u201Cmeter bridge\u201D for transcript \u2014 keeps one-line layout, adds depth */\n#ttp-ecom-center {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n justify-content: center;\n text-align: start;\n padding: 7px 12px 7px 14px;\n border-radius: 16px;\n background: rgba(0, 0, 0, 0.16);\n border: 1px solid rgba(255, 255, 255, 0.08);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.07),\n inset 0 -1px 0 rgba(0, 0, 0, 0.12);\n}\n\n#ttp-ecom-live-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-width: 0;\n}\n\n#ttp-ecom-live-label {\n font-size: 9px;\n font-weight: 800;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: var(--ecom-accent, #4ade80);\n opacity: 0.98;\n white-space: nowrap;\n}\n\n#ttp-ecom-dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--ecom-accent, #4ade80);\n flex-shrink: 0;\n box-shadow: 0 0 14px rgba(74, 222, 128, 0.45);\n animation: ttp-ecom-blink 1.35s ease-in-out infinite;\n}\n#ttp-ecom-dot.paused {\n animation: none;\n opacity: 0.45;\n background: rgba(255,255,255,0.35);\n box-shadow: none;\n}\n@keyframes ttp-ecom-blink {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.25; transform: scale(0.92); }\n}\n\n#ttp-ecom-transcript {\n font-size: 12px;\n line-height: 1.42;\n letter-spacing: 0.015em;\n color: rgba(255, 255, 255, 0.94);\n width: 100%;\n max-width: 100%;\n overflow: hidden;\n word-break: break-word;\n overflow-wrap: anywhere;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n line-clamp: 2;\n}\n\n#ttp-ecom-transcript.ttp-ecom-transcript--user {\n color: rgba(255, 244, 214, 0.98);\n font-weight: 600;\n letter-spacing: 0.02em;\n text-shadow: 0 0 28px rgba(251, 191, 36, 0.22);\n}\n\n/* Squircle glass controls */\n#ttp-ecom-strip .ttp-ecom-ctrl {\n width: 36px;\n height: 36px;\n border-radius: 12px;\n border: 1px solid rgba(255, 255, 255, 0.16);\n background: linear-gradient(165deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0.05) 100%);\n color: rgba(255, 255, 255, 0.92);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n position: relative;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.18),\n 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.14s ease;\n outline: none;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl:hover {\n background: linear-gradient(165deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.08) 100%);\n border-color: rgba(255, 255, 255, 0.32);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.22),\n 0 4px 14px rgba(0, 0, 0, 0.2);\n}\n#ttp-ecom-strip .ttp-ecom-ctrl:active { transform: scale(0.94); }\n#ttp-ecom-strip .ttp-ecom-ctrl:focus-visible {\n outline: 2px solid rgba(165, 180, 252, 0.95);\n outline-offset: 2px;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-active {\n background: linear-gradient(165deg, rgba(129, 140, 248, 0.45) 0%, rgba(99, 102, 241, 0.28) 100%) !important;\n border-color: rgba(196, 181, 253, 0.65) !important;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 0 1px rgba(99, 102, 241, 0.35),\n 0 6px 18px rgba(79, 70, 229, 0.35) !important;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-warn {\n background: linear-gradient(165deg, rgba(252, 165, 165, 0.22) 0%, rgba(239, 68, 68, 0.2) 100%) !important;\n border-color: rgba(252, 165, 165, 0.55) !important;\n}\n\n#ttp-ecom-strip .ttp-ecom-ctrl-end {\n width: 40px;\n height: 40px;\n border-radius: 14px;\n background: linear-gradient(165deg, #fb7185 0%, var(--ecom-end, #ef4444) 52%, #991b1b 100%) !important;\n border: none !important;\n color: #fff !important;\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.25),\n 0 0 0 2px rgba(0, 0, 0, 0.12),\n 0 6px 22px rgba(239, 68, 68, 0.48);\n transform: rotate(135deg);\n transition: filter 0.18s ease, transform 0.14s ease, box-shadow 0.2s ease;\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-end:hover {\n filter: brightness(1.06);\n transform: rotate(135deg) scale(1.05);\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.28),\n 0 0 0 2px rgba(0, 0, 0, 0.12),\n 0 10px 28px rgba(239, 68, 68, 0.52);\n}\n#ttp-ecom-strip .ttp-ecom-ctrl-end:active {\n transform: rotate(135deg) scale(0.94);\n}\n\n/* Mini waveform */\n#ttp-ecom-strip .ttp-ecom-mini-wave {\n display: flex;\n align-items: center;\n gap: 3px;\n height: 24px;\n padding: 0 4px;\n opacity: 0.9;\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb {\n width: 3px;\n border-radius: 3px;\n background: linear-gradient(180deg, #ddd6fe 0%, var(--ecom-accent, #a78bfa) 100%);\n animation: ttp-ecom-wa 0.78s ease-in-out infinite;\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(1) { height: 6px; animation-delay: 0s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(2) { height: 11px; animation-delay: 0.1s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(3) { height: 16px; animation-delay: 0.2s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(4) { height: 9px; animation-delay: 0.15s; }\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb:nth-child(5) { height: 12px; animation-delay: 0.05s; }\n@keyframes ttp-ecom-wa {\n 0%, 100% { transform: scaleY(0.38); opacity: 0.5; }\n 50% { transform: scaleY(1); opacity: 1; }\n}\n#ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb.paused {\n animation-play-state: paused;\n transform: scaleY(0.32);\n opacity: 0.28;\n}\n\n/* Input row */\n#ttp-ecom-input-row {\n display: none;\n position: relative;\n z-index: 1;\n align-items: center;\n gap: 10px;\n padding: 0 14px 12px;\n margin-top: -2px;\n border-top: 1px solid rgba(255, 255, 255, 0.1);\n}\n#ttp-ecom-input-row.open {\n display: flex;\n}\n#ttp-ecom-input {\n flex: 1;\n height: 40px;\n border-radius: 12px;\n border: 1px solid rgba(255, 255, 255, 0.18);\n background: rgba(0, 0, 0, 0.22);\n color: #fff;\n font-size: 14px;\n padding: 0 14px;\n outline: none;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);\n transition: border-color 0.18s ease, box-shadow 0.18s ease;\n}\n#ttp-ecom-input::placeholder { color: rgba(255, 255, 255, 0.42); }\n#ttp-ecom-input:focus {\n border-color: rgba(165, 180, 252, 0.65);\n box-shadow:\n inset 0 1px 2px rgba(0, 0, 0, 0.2),\n 0 0 0 3px rgba(99, 102, 241, 0.25);\n}\n\n#ttp-ecom-strip .ttp-ecom-send {\n width: 36px;\n height: 36px;\n border-radius: 12px;\n border: none;\n background: linear-gradient(165deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.1) 100%);\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);\n transition: background 0.18s ease, transform 0.12s ease;\n}\n#ttp-ecom-strip .ttp-ecom-send:hover {\n background: linear-gradient(165deg, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0.14) 100%);\n}\n#ttp-ecom-strip .ttp-ecom-send:active { transform: scale(0.94); }\n\n@media (max-width: 520px) {\n #ttp-ecom-strip .ttp-ecom-mini-wave { display: none; }\n #ttp-ecom-main-row { gap: 7px; padding: 16px 12px 10px; }\n #ttp-ecom-strip .ttp-ecom-ctrl { width: 36px; height: 36px; }\n #ttp-ecom-strip .ttp-ecom-ctrl-end { width: 40px; height: 40px; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n #ttp-ecom-dot { animation: none; opacity: 0.9; }\n #ttp-ecom-strip .ttp-ecom-mini-wave .ttp-ecom-wb { animation: none; opacity: 0.65; }\n}\n";
|
|
13902
14079
|
|
|
13903
14080
|
/***/ }),
|
|
13904
14081
|
|
|
@@ -15519,7 +15696,7 @@ var PartnerScriptRunner = /*#__PURE__*/function () {
|
|
|
15519
15696
|
value: (function () {
|
|
15520
15697
|
var _runAdapterBody2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(action, args, entry) {
|
|
15521
15698
|
var _entry$version4;
|
|
15522
|
-
var eventName, safeArgs, productIds, _productIds$, idStr, _idStr, ctx, result, postCtx, _t3, _t4, _t5;
|
|
15699
|
+
var eventName, safeArgs, productIds, _productIds$, idStr, _idStr, ctx, result, _result$totalCount, bytes, kb, extra, postCtx, _t3, _t4, _t5;
|
|
15523
15700
|
return _regenerator().w(function (_context3) {
|
|
15524
15701
|
while (1) switch (_context3.p = _context3.n) {
|
|
15525
15702
|
case 0:
|
|
@@ -15583,6 +15760,19 @@ var PartnerScriptRunner = /*#__PURE__*/function () {
|
|
|
15583
15760
|
error: String((_t4 === null || _t4 === void 0 ? void 0 : _t4.message) || _t4)
|
|
15584
15761
|
});
|
|
15585
15762
|
case 7:
|
|
15763
|
+
// Payload size diagnostics — log before ClientToolsRegistry rejects oversize results.
|
|
15764
|
+
try {
|
|
15765
|
+
bytes = JSON.stringify(result).length;
|
|
15766
|
+
kb = Math.round(bytes / 1024);
|
|
15767
|
+
extra = action === 'search.api' && result && _typeof(result) === 'object' ? " products=".concat(Array.isArray(result.products) ? result.products.length : '?', " totalCount=").concat((_result$totalCount = result.totalCount) !== null && _result$totalCount !== void 0 ? _result$totalCount : '?') : '';
|
|
15768
|
+
console.log("".concat(LOG, " ").concat(action, " done ok=").concat(adapterResultOk(result), " payload=").concat(kb, "KB").concat(extra));
|
|
15769
|
+
if (bytes > 480000) {
|
|
15770
|
+
console.warn("".concat(LOG, " ").concat(action, " payload near/over 512KB wire limit (").concat(kb, "KB) \u2014 backend may see totalCount=0"));
|
|
15771
|
+
}
|
|
15772
|
+
} catch (_unused) {/* ignore circular refs */}
|
|
15773
|
+
|
|
15774
|
+
// Inline post-hook runs only when main succeeded (mirror of after-hook
|
|
15775
|
+
// gating). Best-effort: errors are logged, the main result is still returned.
|
|
15586
15776
|
if (!(entry.postFn && adapterResultOk(result))) {
|
|
15587
15777
|
_context3.n = 11;
|
|
15588
15778
|
break;
|
|
@@ -20113,8 +20303,8 @@ var VoiceSDK = _v2_VoiceSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"];
|
|
|
20113
20303
|
|
|
20114
20304
|
|
|
20115
20305
|
// Version - injected at build time from package.json via webpack DefinePlugin
|
|
20116
|
-
var VERSION = "2.45.
|
|
20117
|
-
var BUILD_TIME = "2026-06-
|
|
20306
|
+
var VERSION = "2.45.14";
|
|
20307
|
+
var BUILD_TIME = "2026-06-29T06:35:24.857Z";
|
|
20118
20308
|
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;');
|
|
20119
20309
|
|
|
20120
20310
|
// Named exports
|
|
@@ -24406,9 +24596,17 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24406
24596
|
// Transcript sync
|
|
24407
24597
|
_this.pendingSentenceText = null; // Text waiting for first audio chunk
|
|
24408
24598
|
_this.pendingSynced = null; // Synced actions waiting for first audio chunk
|
|
24409
|
-
_this.sentenceTimings = []; // [{startTime, text, synced, displayed}, ...]
|
|
24599
|
+
_this.sentenceTimings = []; // [{segmentId, startTime, endTime, text, synced, displayed, doneReported}, ...]
|
|
24410
24600
|
_this.isCheckingTranscripts = false;
|
|
24411
24601
|
|
|
24602
|
+
// Audio segment correlation (backend-assigned id carried on audio_start). pendingSegmentId
|
|
24603
|
+
// waits for the segment's first chunk, then is promoted to currentSegmentId at scheduling.
|
|
24604
|
+
// currentSegmentId is stamped onto playbackStarted/playbackStopped so the backend can match
|
|
24605
|
+
// the "stopped" against the last burst it sent. Per-segment completion is reported via the
|
|
24606
|
+
// 'segmentDone' event (finished / barged_in / interrupted + playedMs).
|
|
24607
|
+
_this.pendingSegmentId = null;
|
|
24608
|
+
_this.currentSegmentId = null;
|
|
24609
|
+
|
|
24412
24610
|
// Flag to prevent queuing new audio after stopImmediate() is called (barge-in protection)
|
|
24413
24611
|
// This prevents race conditions where audio chunks arrive after stop but before sources are stopped
|
|
24414
24612
|
// Cleared when markNewSentence() is called (signals new audio is starting)
|
|
@@ -24790,7 +24988,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24790
24988
|
// Keep scheduling frames as long as we have them and haven't reached the lookahead limit
|
|
24791
24989
|
scheduledCount = 0;
|
|
24792
24990
|
_loop = /*#__PURE__*/_regenerator().m(function _loop() {
|
|
24793
|
-
var preparedFrame, source, currentTime, isMobile, startupBuffer, minStartTime, startTime;
|
|
24991
|
+
var preparedFrame, source, currentTime, isMobile, startupBuffer, minStartTime, segFrameEnd, startTime;
|
|
24794
24992
|
return _regenerator().w(function (_context3) {
|
|
24795
24993
|
while (1) switch (_context3.n) {
|
|
24796
24994
|
case 0:
|
|
@@ -24850,22 +25048,40 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24850
25048
|
// Always use nextStartTime (which is already calculated for seamless playback)
|
|
24851
25049
|
}
|
|
24852
25050
|
|
|
24853
|
-
//
|
|
24854
|
-
|
|
25051
|
+
// Audio-clock window for THIS frame: [nextStartTime, nextStartTime + duration).
|
|
25052
|
+
segFrameEnd = _this4.nextStartTime + preparedFrame.duration; // ✅ MOVED OUTSIDE - Record sentence timing on first chunk of EACH sentence
|
|
25053
|
+
if (_this4.pendingSentenceText || _this4.pendingSegmentId != null) {
|
|
25054
|
+
// First chunk of a new segment: open a timing entry and adopt its id as current.
|
|
24855
25055
|
_this4.sentenceTimings.push({
|
|
25056
|
+
segmentId: _this4.pendingSegmentId,
|
|
24856
25057
|
startTime: _this4.nextStartTime,
|
|
25058
|
+
endTime: segFrameEnd,
|
|
24857
25059
|
text: _this4.pendingSentenceText,
|
|
24858
25060
|
synced: _this4.pendingSynced,
|
|
24859
|
-
displayed: false
|
|
25061
|
+
displayed: false,
|
|
25062
|
+
doneReported: false
|
|
24860
25063
|
});
|
|
24861
|
-
|
|
25064
|
+
_this4.currentSegmentId = _this4.pendingSegmentId;
|
|
25065
|
+
console.log("\uD83D\uDCDD AudioPlayer: Sentence scheduled at ".concat(_this4.nextStartTime.toFixed(3), "s (segmentId: ").concat(_this4.pendingSegmentId, "): \"").concat((_this4.pendingSentenceText || '').substring(0, 40), "...\" (synced: ").concat(_this4.pendingSynced ? _this4.pendingSynced.length : 0, ")"));
|
|
25066
|
+
// Per-segment START signal: this segment's first frame just scheduled (≈ playback start).
|
|
25067
|
+
// Mirrors the per-segment 'segmentDone' (end) event; lets the backend fire speech-synced
|
|
25068
|
+
// actions exactly when THIS line begins playing (vs the coarse, once-per-burst playbackStarted).
|
|
25069
|
+
if (_this4.currentSegmentId != null) {
|
|
25070
|
+
_this4.emit('segmentStarted', {
|
|
25071
|
+
segmentId: _this4.currentSegmentId
|
|
25072
|
+
});
|
|
25073
|
+
}
|
|
24862
25074
|
_this4.pendingSentenceText = null;
|
|
24863
25075
|
_this4.pendingSynced = null;
|
|
25076
|
+
_this4.pendingSegmentId = null;
|
|
24864
25077
|
|
|
24865
25078
|
// Start checker if not running
|
|
24866
25079
|
if (!_this4.isCheckingTranscripts) {
|
|
24867
25080
|
_this4.startTranscriptChecker();
|
|
24868
25081
|
}
|
|
25082
|
+
} else if (_this4.sentenceTimings.length > 0) {
|
|
25083
|
+
// Subsequent chunk of the current segment: extend its end on the audio clock.
|
|
25084
|
+
_this4.sentenceTimings[_this4.sentenceTimings.length - 1].endTime = segFrameEnd;
|
|
24869
25085
|
}
|
|
24870
25086
|
|
|
24871
25087
|
// Schedule this chunk to start at nextStartTime
|
|
@@ -24920,8 +25136,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24920
25136
|
if (_this4.scheduledBuffers === 0 && _this4.preparedBuffer.length === 0 && _this4.pcmChunkQueue.length === 0 && !_this4._isStopped) {
|
|
24921
25137
|
_this4.isPlaying = false;
|
|
24922
25138
|
_this4.isSchedulingFrames = false;
|
|
24923
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished)');
|
|
24924
|
-
_this4.emit('playbackStopped'
|
|
25139
|
+
console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished, segmentId: ' + _this4.currentSegmentId + ')');
|
|
25140
|
+
_this4.emit('playbackStopped', {
|
|
25141
|
+
segmentId: _this4.currentSegmentId
|
|
25142
|
+
});
|
|
24925
25143
|
} else if (_this4.preparedBuffer.length > 0 && !_this4._isStopped) {
|
|
24926
25144
|
// More frames available, schedule them immediately
|
|
24927
25145
|
|
|
@@ -24957,8 +25175,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24957
25175
|
};
|
|
24958
25176
|
if (!_this4.isPlaying) {
|
|
24959
25177
|
_this4.isPlaying = true;
|
|
24960
|
-
console.log('🎵 AudioPlayer: Emitting playbackStarted event');
|
|
24961
|
-
_this4.emit('playbackStarted'
|
|
25178
|
+
console.log('🎵 AudioPlayer: Emitting playbackStarted event (segmentId: ' + _this4.currentSegmentId + ')');
|
|
25179
|
+
_this4.emit('playbackStarted', {
|
|
25180
|
+
segmentId: _this4.currentSegmentId
|
|
25181
|
+
});
|
|
24962
25182
|
}
|
|
24963
25183
|
case 3:
|
|
24964
25184
|
return _context3.a(2);
|
|
@@ -26302,14 +26522,66 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26302
26522
|
// Note: scheduledBuffers was already reset to 0 above when clearing scheduledSources
|
|
26303
26523
|
this.nextStartTime = 0;
|
|
26304
26524
|
|
|
26525
|
+
// Report per-segment completion for the interrupted burst BEFORE clearing timing state.
|
|
26526
|
+
// Audible segment → barged_in (ms heard); scheduled-but-unstarted → interrupted;
|
|
26527
|
+
// already-elapsed but unreported → finished. Plus any pending segment (audio_start arrived
|
|
26528
|
+
// but no chunks scheduled yet) → interrupted.
|
|
26529
|
+
try {
|
|
26530
|
+
var nowTs = this.audioContext ? this.audioContext.currentTime : 0;
|
|
26531
|
+
var _iterator = _createForOfIteratorHelper(this.sentenceTimings),
|
|
26532
|
+
_step;
|
|
26533
|
+
try {
|
|
26534
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
26535
|
+
var timing = _step.value;
|
|
26536
|
+
if (timing.doneReported) continue;
|
|
26537
|
+
timing.doneReported = true;
|
|
26538
|
+
var status = void 0,
|
|
26539
|
+
playedMs = void 0;
|
|
26540
|
+
if (timing.endTime != null && nowTs >= timing.endTime) {
|
|
26541
|
+
status = 'finished';
|
|
26542
|
+
playedMs = Math.round((timing.endTime - timing.startTime) * 1000);
|
|
26543
|
+
} else if (nowTs <= timing.startTime) {
|
|
26544
|
+
status = 'interrupted';
|
|
26545
|
+
playedMs = 0;
|
|
26546
|
+
} else {
|
|
26547
|
+
status = 'barged_in';
|
|
26548
|
+
playedMs = Math.round((nowTs - timing.startTime) * 1000);
|
|
26549
|
+
}
|
|
26550
|
+
this.emit('segmentDone', {
|
|
26551
|
+
segmentId: timing.segmentId,
|
|
26552
|
+
status: status,
|
|
26553
|
+
playedMs: playedMs
|
|
26554
|
+
});
|
|
26555
|
+
}
|
|
26556
|
+
} catch (err) {
|
|
26557
|
+
_iterator.e(err);
|
|
26558
|
+
} finally {
|
|
26559
|
+
_iterator.f();
|
|
26560
|
+
}
|
|
26561
|
+
if (this.pendingSegmentId != null) {
|
|
26562
|
+
this.emit('segmentDone', {
|
|
26563
|
+
segmentId: this.pendingSegmentId,
|
|
26564
|
+
status: 'interrupted',
|
|
26565
|
+
playedMs: 0
|
|
26566
|
+
});
|
|
26567
|
+
}
|
|
26568
|
+
} catch (e) {
|
|
26569
|
+
console.warn('⚠️ AudioPlayer: segmentDone (barge-in) reporting failed:', e && e.message);
|
|
26570
|
+
}
|
|
26571
|
+
// Capture the last segment that was playing for the coarse playbackStopped below
|
|
26572
|
+
// (clearTranscriptState resets currentSegmentId).
|
|
26573
|
+
var stoppedSegmentId = this.currentSegmentId;
|
|
26574
|
+
|
|
26305
26575
|
// Clear transcript state
|
|
26306
26576
|
this.clearTranscriptState();
|
|
26307
26577
|
|
|
26308
26578
|
// Emit stopped event - CRITICAL for barge-in
|
|
26309
26579
|
|
|
26310
26580
|
if (wasPlaying) {
|
|
26311
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called)');
|
|
26312
|
-
this.emit('playbackStopped'
|
|
26581
|
+
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called, segmentId: ' + stoppedSegmentId + ')');
|
|
26582
|
+
this.emit('playbackStopped', {
|
|
26583
|
+
segmentId: stoppedSegmentId
|
|
26584
|
+
});
|
|
26313
26585
|
}
|
|
26314
26586
|
}
|
|
26315
26587
|
|
|
@@ -26319,7 +26591,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26319
26591
|
*/
|
|
26320
26592
|
}, {
|
|
26321
26593
|
key: "markNewSentence",
|
|
26322
|
-
value: function markNewSentence(text, synced) {
|
|
26594
|
+
value: function markNewSentence(text, synced, segmentId) {
|
|
26323
26595
|
var _this0 = this;
|
|
26324
26596
|
var wasStopped = this._isStopped;
|
|
26325
26597
|
var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
|
|
@@ -26364,10 +26636,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26364
26636
|
console.log("\uD83D\uDCDD AudioPlayer: New sentence queued while audio playing - will start after current sentence finishes");
|
|
26365
26637
|
}
|
|
26366
26638
|
|
|
26367
|
-
// Always update pending sentence text
|
|
26639
|
+
// Always update pending sentence text, synced actions (for transcript display), and the
|
|
26640
|
+
// backend-assigned segment id (echoed back on the playback events for this segment).
|
|
26368
26641
|
this.pendingSentenceText = text;
|
|
26369
26642
|
this.pendingSynced = synced || null;
|
|
26370
|
-
|
|
26643
|
+
this.pendingSegmentId = segmentId != null ? segmentId : null;
|
|
26644
|
+
console.log("\uD83D\uDCDD AudioPlayer: New sentence marked (segmentId: ".concat(this.pendingSegmentId, "): \"").concat(text.substring(0, 40), "...\" (wasStopped: ").concat(wasStopped, ", isPlaying: ").concat(isCurrentlyPlaying, ", synced: ").concat(synced ? synced.length : 0, ")"));
|
|
26371
26645
|
|
|
26372
26646
|
// CRITICAL: Set timeout to detect empty sentences (audio_start but no chunks)
|
|
26373
26647
|
// This prevents queue blocking if backend sends audio_start but no audio chunks follow
|
|
@@ -26379,6 +26653,18 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26379
26653
|
// Check if this sentence still has no chunks after timeout
|
|
26380
26654
|
if (_this0.pendingSentenceText === sentenceText && _this0.scheduledBuffers === 0 && _this0.preparedBuffer.length === 0 && _this0.pcmChunkQueue.length === 0 && !_this0._isStopped) {
|
|
26381
26655
|
console.warn("\u26A0\uFE0F AudioPlayer: Empty sentence detected after 5s timeout - no chunks received for: \"".concat(sentenceText.substring(0, 40), "...\""));
|
|
26656
|
+
// If this empty sentence carried a segment id, report it done (nothing was heard) and
|
|
26657
|
+
// adopt it as current so the coarse stop below matches the backend's last-sent id.
|
|
26658
|
+
if (_this0.pendingSegmentId != null) {
|
|
26659
|
+
var emptySegId = _this0.pendingSegmentId;
|
|
26660
|
+
_this0.currentSegmentId = emptySegId;
|
|
26661
|
+
_this0.pendingSegmentId = null;
|
|
26662
|
+
_this0.emit('segmentDone', {
|
|
26663
|
+
segmentId: emptySegId,
|
|
26664
|
+
status: 'finished',
|
|
26665
|
+
playedMs: 0
|
|
26666
|
+
});
|
|
26667
|
+
}
|
|
26382
26668
|
// Clear pending sentence to unblock next sentence
|
|
26383
26669
|
if (_this0.pendingSentenceText === sentenceText) {
|
|
26384
26670
|
_this0.pendingSentenceText = null;
|
|
@@ -26387,7 +26673,9 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26387
26673
|
// Only if we're not currently playing (to avoid interrupting real playback)
|
|
26388
26674
|
if (!_this0.isPlaying && _this0.scheduledSources.size === 0) {
|
|
26389
26675
|
console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
|
|
26390
|
-
_this0.emit('playbackStopped'
|
|
26676
|
+
_this0.emit('playbackStopped', {
|
|
26677
|
+
segmentId: _this0.currentSegmentId
|
|
26678
|
+
});
|
|
26391
26679
|
}
|
|
26392
26680
|
}
|
|
26393
26681
|
_this0._emptySentenceTimeout = null;
|
|
@@ -26407,31 +26695,64 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26407
26695
|
var _checkLoop = function checkLoop() {
|
|
26408
26696
|
if (!_this1.isCheckingTranscripts || !_this1.audioContext) return;
|
|
26409
26697
|
var currentTime = _this1.audioContext.currentTime;
|
|
26410
|
-
var
|
|
26411
|
-
|
|
26698
|
+
var _iterator2 = _createForOfIteratorHelper(_this1.sentenceTimings),
|
|
26699
|
+
_step2;
|
|
26412
26700
|
try {
|
|
26413
|
-
for (
|
|
26414
|
-
var
|
|
26415
|
-
if (!
|
|
26416
|
-
|
|
26701
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
26702
|
+
var _timing = _step2.value;
|
|
26703
|
+
if (!_timing.displayed && _timing.text && currentTime >= _timing.startTime) {
|
|
26704
|
+
_timing.displayed = true;
|
|
26417
26705
|
var eventData = {
|
|
26418
|
-
text:
|
|
26706
|
+
text: _timing.text
|
|
26419
26707
|
};
|
|
26420
|
-
if (
|
|
26421
|
-
eventData.synced =
|
|
26708
|
+
if (_timing.synced) {
|
|
26709
|
+
eventData.synced = _timing.synced;
|
|
26422
26710
|
}
|
|
26423
|
-
console.log("\uD83D\uDCDD AudioPlayer: Display transcript at ".concat(currentTime.toFixed(3), "s: \"").concat(
|
|
26711
|
+
console.log("\uD83D\uDCDD AudioPlayer: Display transcript at ".concat(currentTime.toFixed(3), "s: \"").concat(_timing.text.substring(0, 40), "...\" (synced: ").concat(_timing.synced ? _timing.synced.length : 0, ")"));
|
|
26424
26712
|
_this1.emit('transcriptDisplay', eventData);
|
|
26425
26713
|
}
|
|
26714
|
+
// Per-segment natural finish: this segment's audio window has fully elapsed.
|
|
26715
|
+
if (!_timing.doneReported && _timing.endTime != null && currentTime >= _timing.endTime) {
|
|
26716
|
+
_timing.doneReported = true;
|
|
26717
|
+
var _playedMs = Math.round((_timing.endTime - _timing.startTime) * 1000);
|
|
26718
|
+
_this1.emit('segmentDone', {
|
|
26719
|
+
segmentId: _timing.segmentId,
|
|
26720
|
+
status: 'finished',
|
|
26721
|
+
playedMs: _playedMs
|
|
26722
|
+
});
|
|
26723
|
+
}
|
|
26426
26724
|
}
|
|
26427
26725
|
} catch (err) {
|
|
26428
|
-
|
|
26726
|
+
_iterator2.e(err);
|
|
26429
26727
|
} finally {
|
|
26430
|
-
|
|
26728
|
+
_iterator2.f();
|
|
26431
26729
|
}
|
|
26432
26730
|
if (_this1.isPlaying || _this1.scheduledBuffers > 0) {
|
|
26433
26731
|
requestAnimationFrame(_checkLoop);
|
|
26434
26732
|
} else {
|
|
26733
|
+
// Playback drained naturally — flush any segment whose finish tick we may have missed
|
|
26734
|
+
// (the last buffer's onended can flip isPlaying=false before this loop's next tick).
|
|
26735
|
+
var _iterator3 = _createForOfIteratorHelper(_this1.sentenceTimings),
|
|
26736
|
+
_step3;
|
|
26737
|
+
try {
|
|
26738
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
26739
|
+
var timing = _step3.value;
|
|
26740
|
+
if (!timing.doneReported) {
|
|
26741
|
+
timing.doneReported = true;
|
|
26742
|
+
var end = timing.endTime != null ? timing.endTime : timing.startTime;
|
|
26743
|
+
var playedMs = Math.round((end - timing.startTime) * 1000);
|
|
26744
|
+
_this1.emit('segmentDone', {
|
|
26745
|
+
segmentId: timing.segmentId,
|
|
26746
|
+
status: 'finished',
|
|
26747
|
+
playedMs: playedMs
|
|
26748
|
+
});
|
|
26749
|
+
}
|
|
26750
|
+
}
|
|
26751
|
+
} catch (err) {
|
|
26752
|
+
_iterator3.e(err);
|
|
26753
|
+
} finally {
|
|
26754
|
+
_iterator3.f();
|
|
26755
|
+
}
|
|
26435
26756
|
_this1.isCheckingTranscripts = false;
|
|
26436
26757
|
console.log('📝 AudioPlayer: Transcript checker stopped');
|
|
26437
26758
|
}
|
|
@@ -26447,6 +26768,8 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26447
26768
|
value: function clearTranscriptState() {
|
|
26448
26769
|
this.pendingSentenceText = null;
|
|
26449
26770
|
this.pendingSynced = null;
|
|
26771
|
+
this.pendingSegmentId = null;
|
|
26772
|
+
this.currentSegmentId = null;
|
|
26450
26773
|
this.sentenceTimings = [];
|
|
26451
26774
|
this.isCheckingTranscripts = false;
|
|
26452
26775
|
console.log('📝 AudioPlayer: Transcript state cleared');
|
|
@@ -26596,13 +26919,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26596
26919
|
/* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
|
|
26597
26920
|
/* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
|
|
26598
26921
|
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); }
|
|
26922
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
26923
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
26924
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
26599
26925
|
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 }; })(); }
|
|
26600
26926
|
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); }
|
|
26601
26927
|
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); }
|
|
26602
26928
|
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); }); }; }
|
|
26603
|
-
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
26604
|
-
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
26605
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
26606
26929
|
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; }
|
|
26607
26930
|
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; }
|
|
26608
26931
|
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
@@ -27169,19 +27492,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27169
27492
|
key: "setupAudioPlayerEvents",
|
|
27170
27493
|
value: function setupAudioPlayerEvents() {
|
|
27171
27494
|
var _this3 = this;
|
|
27172
|
-
this.audioPlayer.on('playbackStarted', function () {
|
|
27495
|
+
this.audioPlayer.on('playbackStarted', function (info) {
|
|
27173
27496
|
_this3.isPlaying = true;
|
|
27174
27497
|
_this3.emit('playbackStarted');
|
|
27175
27498
|
|
|
27176
27499
|
// Transcripts are displayed when they arrive (between sentences)
|
|
27177
27500
|
// No need to handle transcript display here - it's handled in handleTranscript()
|
|
27178
27501
|
|
|
27179
|
-
// Notify server - CRITICAL for barge-in detection
|
|
27502
|
+
// Notify server - CRITICAL for barge-in detection.
|
|
27503
|
+
// Carry the segmentId of the burst that started playing (echoed from audio_start) so the
|
|
27504
|
+
// backend can correlate playback events with the bursts it sent.
|
|
27180
27505
|
|
|
27181
27506
|
if (_this3.isConnected) {
|
|
27182
|
-
|
|
27507
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27508
|
+
console.log('📤 VoiceSDK v2: Sending audio_started_playing message to server (segmentId: ' + segmentId + ')');
|
|
27183
27509
|
_this3.sendMessage({
|
|
27184
|
-
t: 'audio_started_playing'
|
|
27510
|
+
t: 'audio_started_playing',
|
|
27511
|
+
segmentId: segmentId
|
|
27185
27512
|
});
|
|
27186
27513
|
} else {
|
|
27187
27514
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_started_playing - not connected');
|
|
@@ -27205,39 +27532,62 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27205
27532
|
_this3.emit('transcriptDisplay', fullTranscriptData);
|
|
27206
27533
|
_this3.emit('transcript', fullTranscriptData);
|
|
27207
27534
|
if (transcriptData.synced && Array.isArray(transcriptData.synced)) {
|
|
27208
|
-
console.log("\uD83D\uDCDD VoiceSDK v2:
|
|
27209
|
-
|
|
27210
|
-
_step;
|
|
27211
|
-
try {
|
|
27212
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
27213
|
-
var action = _step.value;
|
|
27214
|
-
_this3.emit('message', action);
|
|
27215
|
-
}
|
|
27216
|
-
} catch (err) {
|
|
27217
|
-
_iterator.e(err);
|
|
27218
|
-
} finally {
|
|
27219
|
-
_iterator.f();
|
|
27220
|
-
}
|
|
27535
|
+
console.log("\uD83D\uDCDD VoiceSDK v2: Dispatching ".concat(transcriptData.synced.length, " synced action(s)"));
|
|
27536
|
+
void _this3._dispatchSyncedActions(transcriptData.synced);
|
|
27221
27537
|
}
|
|
27222
27538
|
});
|
|
27223
|
-
this.audioPlayer.on('playbackStopped', function () {
|
|
27539
|
+
this.audioPlayer.on('playbackStopped', function (info) {
|
|
27224
27540
|
_this3.isPlaying = false;
|
|
27225
27541
|
_this3.emit('playbackStopped');
|
|
27226
27542
|
|
|
27227
27543
|
// When playback stops, keep currentPlayingSentenceId to track which sentence just finished
|
|
27228
27544
|
// The next transcript will arrive between sentences and will be displayed immediately
|
|
27229
27545
|
|
|
27230
|
-
// Notify server - CRITICAL for barge-in detection
|
|
27546
|
+
// Notify server - CRITICAL for barge-in detection.
|
|
27547
|
+
// Carry the segmentId of the last burst that was playing so the backend's idle gate can
|
|
27548
|
+
// match this stop against the last burst it sent (deterministic "fully idle").
|
|
27231
27549
|
|
|
27232
27550
|
if (_this3.isConnected) {
|
|
27233
|
-
|
|
27551
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27552
|
+
console.log('📤 VoiceSDK v2: Sending audio_stopped_playing message to server (segmentId: ' + segmentId + ')');
|
|
27234
27553
|
_this3.sendMessage({
|
|
27235
|
-
t: 'audio_stopped_playing'
|
|
27554
|
+
t: 'audio_stopped_playing',
|
|
27555
|
+
segmentId: segmentId
|
|
27236
27556
|
});
|
|
27237
27557
|
} else {
|
|
27238
27558
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_stopped_playing - not connected');
|
|
27239
27559
|
}
|
|
27240
27560
|
});
|
|
27561
|
+
|
|
27562
|
+
// Per-segment playback completion (finished / barged_in / interrupted) with the ms of THIS
|
|
27563
|
+
// segment actually heard. Additive telemetry alongside the coarse started/stopped events.
|
|
27564
|
+
|
|
27565
|
+
this.audioPlayer.on('segmentDone', function (info) {
|
|
27566
|
+
if (!info) return;
|
|
27567
|
+
if (_this3.isConnected) {
|
|
27568
|
+
console.log('📤 VoiceSDK v2: Sending audio_segment_done (segmentId: ' + info.segmentId + ', status: ' + info.status + ', playedMs: ' + info.playedMs + ')');
|
|
27569
|
+
_this3.sendMessage({
|
|
27570
|
+
t: 'audio_segment_done',
|
|
27571
|
+
segmentId: info.segmentId != null ? info.segmentId : null,
|
|
27572
|
+
status: info.status,
|
|
27573
|
+
playedMs: info.playedMs
|
|
27574
|
+
});
|
|
27575
|
+
}
|
|
27576
|
+
});
|
|
27577
|
+
|
|
27578
|
+
// Per-segment START — fired when a sentence's first frame schedules (≈ it begins playing).
|
|
27579
|
+
// The backend uses this to fire sync_with_speech tool execution exactly as the line is heard.
|
|
27580
|
+
|
|
27581
|
+
this.audioPlayer.on('segmentStarted', function (info) {
|
|
27582
|
+
if (!info || info.segmentId == null) return;
|
|
27583
|
+
if (_this3.isConnected) {
|
|
27584
|
+
console.log('📤 VoiceSDK v2: Sending audio_segment_started (segmentId: ' + info.segmentId + ')');
|
|
27585
|
+
_this3.sendMessage({
|
|
27586
|
+
t: 'audio_segment_started',
|
|
27587
|
+
segmentId: info.segmentId
|
|
27588
|
+
});
|
|
27589
|
+
}
|
|
27590
|
+
});
|
|
27241
27591
|
this.audioPlayer.on('playbackError', function (error) {
|
|
27242
27592
|
_this3.emit('playbackError', error);
|
|
27243
27593
|
_this3.emit('error', error);
|
|
@@ -27602,7 +27952,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27602
27952
|
|
|
27603
27953
|
// Include SDK build time for debugging
|
|
27604
27954
|
if (true) {
|
|
27605
|
-
helloMessage.lastBuildTime = "2026-06-
|
|
27955
|
+
helloMessage.lastBuildTime = "2026-06-29T06:35:24.857Z";
|
|
27606
27956
|
}
|
|
27607
27957
|
|
|
27608
27958
|
// Page context is intentionally NOT attached to the hello message.
|
|
@@ -27757,7 +28107,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27757
28107
|
case 'audio_start':
|
|
27758
28108
|
// Backend sends audio_start with transcript text before audio chunks
|
|
27759
28109
|
// Store the text in AudioPlayer for synced display when audio actually starts playing
|
|
27760
|
-
console.log('📝 VoiceSDK v2: Received audio_start with text:', message.text);
|
|
28110
|
+
console.log('📝 VoiceSDK v2: Received audio_start with text:', message.text, '(segmentId:', message.segmentId, ')');
|
|
27761
28111
|
|
|
27762
28112
|
// CRITICAL: Record timestamp to prevent premature stop_playing messages from cutting sentences
|
|
27763
28113
|
this.lastAudioStartTime = Date.now();
|
|
@@ -27773,7 +28123,10 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27773
28123
|
if (synced) {
|
|
27774
28124
|
console.log("\uD83D\uDCDD VoiceSDK v2: audio_start carries ".concat(synced.length, " synced action(s)"));
|
|
27775
28125
|
}
|
|
27776
|
-
|
|
28126
|
+
// Pass the backend-assigned segmentId (may be undefined for legacy backends) so the
|
|
28127
|
+
// player can echo it back on this segment's playback events.
|
|
28128
|
+
var segmentId = message.segmentId != null ? message.segmentId : null;
|
|
28129
|
+
this.audioPlayer.markNewSentence(message.text, synced, segmentId);
|
|
27777
28130
|
}
|
|
27778
28131
|
// Also emit as message for other listeners
|
|
27779
28132
|
this.emit('message', message);
|
|
@@ -28302,6 +28655,104 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28302
28655
|
}
|
|
28303
28656
|
}
|
|
28304
28657
|
|
|
28658
|
+
/**
|
|
28659
|
+
* Dispatch widget actions synced to a TTS sentence boundary.
|
|
28660
|
+
* run_partner_script envelopes must go through the same handler as WS traffic
|
|
28661
|
+
* (show_media and other t= messages still emit as generic message events).
|
|
28662
|
+
* @private
|
|
28663
|
+
*/
|
|
28664
|
+
}, {
|
|
28665
|
+
key: "_dispatchSyncedActions",
|
|
28666
|
+
value: (function () {
|
|
28667
|
+
var _dispatchSyncedActions2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(actions) {
|
|
28668
|
+
var _iterator, _step, raw, _t2;
|
|
28669
|
+
return _regenerator().w(function (_context3) {
|
|
28670
|
+
while (1) switch (_context3.p = _context3.n) {
|
|
28671
|
+
case 0:
|
|
28672
|
+
_iterator = _createForOfIteratorHelper(actions);
|
|
28673
|
+
_context3.p = 1;
|
|
28674
|
+
_iterator.s();
|
|
28675
|
+
case 2:
|
|
28676
|
+
if ((_step = _iterator.n()).done) {
|
|
28677
|
+
_context3.n = 4;
|
|
28678
|
+
break;
|
|
28679
|
+
}
|
|
28680
|
+
raw = _step.value;
|
|
28681
|
+
_context3.n = 3;
|
|
28682
|
+
return this._dispatchSyncedAction(raw);
|
|
28683
|
+
case 3:
|
|
28684
|
+
_context3.n = 2;
|
|
28685
|
+
break;
|
|
28686
|
+
case 4:
|
|
28687
|
+
_context3.n = 6;
|
|
28688
|
+
break;
|
|
28689
|
+
case 5:
|
|
28690
|
+
_context3.p = 5;
|
|
28691
|
+
_t2 = _context3.v;
|
|
28692
|
+
_iterator.e(_t2);
|
|
28693
|
+
case 6:
|
|
28694
|
+
_context3.p = 6;
|
|
28695
|
+
_iterator.f();
|
|
28696
|
+
return _context3.f(6);
|
|
28697
|
+
case 7:
|
|
28698
|
+
return _context3.a(2);
|
|
28699
|
+
}
|
|
28700
|
+
}, _callee3, this, [[1, 5, 6, 7]]);
|
|
28701
|
+
}));
|
|
28702
|
+
function _dispatchSyncedActions(_x) {
|
|
28703
|
+
return _dispatchSyncedActions2.apply(this, arguments);
|
|
28704
|
+
}
|
|
28705
|
+
return _dispatchSyncedActions;
|
|
28706
|
+
}())
|
|
28707
|
+
}, {
|
|
28708
|
+
key: "_dispatchSyncedAction",
|
|
28709
|
+
value: function () {
|
|
28710
|
+
var _dispatchSyncedAction2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(action) {
|
|
28711
|
+
var message, _t3;
|
|
28712
|
+
return _regenerator().w(function (_context4) {
|
|
28713
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
28714
|
+
case 0:
|
|
28715
|
+
message = action;
|
|
28716
|
+
if (!(typeof message === 'string')) {
|
|
28717
|
+
_context4.n = 3;
|
|
28718
|
+
break;
|
|
28719
|
+
}
|
|
28720
|
+
_context4.p = 1;
|
|
28721
|
+
message = JSON.parse(message);
|
|
28722
|
+
_context4.n = 3;
|
|
28723
|
+
break;
|
|
28724
|
+
case 2:
|
|
28725
|
+
_context4.p = 2;
|
|
28726
|
+
_t3 = _context4.v;
|
|
28727
|
+
console.warn('⚠️ VoiceSDK v2: Ignoring invalid synced action string:', action);
|
|
28728
|
+
return _context4.a(2);
|
|
28729
|
+
case 3:
|
|
28730
|
+
if (!(!message || _typeof(message) !== 'object')) {
|
|
28731
|
+
_context4.n = 4;
|
|
28732
|
+
break;
|
|
28733
|
+
}
|
|
28734
|
+
return _context4.a(2);
|
|
28735
|
+
case 4:
|
|
28736
|
+
if (!(message.t === 'run_partner_script')) {
|
|
28737
|
+
_context4.n = 6;
|
|
28738
|
+
break;
|
|
28739
|
+
}
|
|
28740
|
+
_context4.n = 5;
|
|
28741
|
+
return this._handleRunPartnerScript(message);
|
|
28742
|
+
case 5:
|
|
28743
|
+
return _context4.a(2);
|
|
28744
|
+
case 6:
|
|
28745
|
+
this.emit('message', message);
|
|
28746
|
+
case 7:
|
|
28747
|
+
return _context4.a(2);
|
|
28748
|
+
}
|
|
28749
|
+
}, _callee4, this, [[1, 2]]);
|
|
28750
|
+
}));
|
|
28751
|
+
function _dispatchSyncedAction(_x2) {
|
|
28752
|
+
return _dispatchSyncedAction2.apply(this, arguments);
|
|
28753
|
+
}
|
|
28754
|
+
return _dispatchSyncedAction;
|
|
28755
|
+
}()
|
|
28305
28756
|
/**
|
|
28306
28757
|
* Handle a run_partner_script envelope (async partner-adapter dispatch).
|
|
28307
28758
|
*
|
|
@@ -28320,30 +28771,30 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28320
28771
|
}, {
|
|
28321
28772
|
key: "_handleRunPartnerScript",
|
|
28322
28773
|
value: (function () {
|
|
28323
|
-
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28774
|
+
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(message) {
|
|
28324
28775
|
var _this$clientToolsRegi;
|
|
28325
|
-
var _ref, requestId, partnerId, action, args, handler, startedAt, result, elapsedMs, ok, reason, extras, preview, _elapsedMs,
|
|
28326
|
-
return _regenerator().w(function (
|
|
28327
|
-
while (1) switch (
|
|
28776
|
+
var _ref, requestId, partnerId, action, args, handler, startedAt, result, elapsedMs, ok, reason, extras, preview, _elapsedMs, _t4;
|
|
28777
|
+
return _regenerator().w(function (_context5) {
|
|
28778
|
+
while (1) switch (_context5.p = _context5.n) {
|
|
28328
28779
|
case 0:
|
|
28329
28780
|
_ref = message || {}, requestId = _ref.requestId, partnerId = _ref.partnerId, action = _ref.action;
|
|
28330
28781
|
args = message && message.args || {};
|
|
28331
28782
|
if (requestId) {
|
|
28332
|
-
|
|
28783
|
+
_context5.n = 1;
|
|
28333
28784
|
break;
|
|
28334
28785
|
}
|
|
28335
28786
|
console.warn('⚠️ VoiceSDK v2: run_partner_script missing requestId; dropping', message);
|
|
28336
|
-
return
|
|
28787
|
+
return _context5.a(2);
|
|
28337
28788
|
case 1:
|
|
28338
28789
|
if (!_core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__.ClientScriptManager.isClientToolsScript(message)) {
|
|
28339
|
-
|
|
28790
|
+
_context5.n = 2;
|
|
28340
28791
|
break;
|
|
28341
28792
|
}
|
|
28342
|
-
return
|
|
28793
|
+
return _context5.a(2, this.clientScriptManager.handleRunPartnerScript(message));
|
|
28343
28794
|
case 2:
|
|
28344
28795
|
handler = (_this$clientToolsRegi = this.clientToolsRegistry) === null || _this$clientToolsRegi === void 0 || (_this$clientToolsRegi = _this$clientToolsRegi.handlers) === null || _this$clientToolsRegi === void 0 ? void 0 : _this$clientToolsRegi.get('run_partner_script');
|
|
28345
28796
|
if (handler) {
|
|
28346
|
-
|
|
28797
|
+
_context5.n = 3;
|
|
28347
28798
|
break;
|
|
28348
28799
|
}
|
|
28349
28800
|
console.error("\uD83E\uDDE9 VoiceSDK v2: no run_partner_script handler registered (ecommerce flavor not loaded?); requestId=".concat(requestId, " partner=").concat(partnerId, " action=").concat(action));
|
|
@@ -28355,18 +28806,18 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28355
28806
|
ok: false,
|
|
28356
28807
|
error: 'no_handler_registered'
|
|
28357
28808
|
});
|
|
28358
|
-
return
|
|
28809
|
+
return _context5.a(2);
|
|
28359
28810
|
case 3:
|
|
28360
28811
|
startedAt = Date.now();
|
|
28361
28812
|
console.log("\uD83E\uDDE9 VoiceSDK v2: run_partner_script dispatch partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId));
|
|
28362
|
-
|
|
28363
|
-
|
|
28813
|
+
_context5.p = 4;
|
|
28814
|
+
_context5.n = 5;
|
|
28364
28815
|
return handler({
|
|
28365
28816
|
action: action,
|
|
28366
28817
|
args: args
|
|
28367
28818
|
});
|
|
28368
28819
|
case 5:
|
|
28369
|
-
result =
|
|
28820
|
+
result = _context5.v;
|
|
28370
28821
|
elapsedMs = Date.now() - startedAt; // Adapters return { ok, ... } themselves. Honor that flag if present;
|
|
28371
28822
|
// otherwise treat presence-of-result as success.
|
|
28372
28823
|
ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; // Surface the failure reason inline so debugging doesn't require pulling
|
|
@@ -28393,27 +28844,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28393
28844
|
ok: ok,
|
|
28394
28845
|
result: result
|
|
28395
28846
|
});
|
|
28396
|
-
|
|
28847
|
+
_context5.n = 7;
|
|
28397
28848
|
break;
|
|
28398
28849
|
case 6:
|
|
28399
|
-
|
|
28400
|
-
|
|
28850
|
+
_context5.p = 6;
|
|
28851
|
+
_t4 = _context5.v;
|
|
28401
28852
|
_elapsedMs = Date.now() - startedAt;
|
|
28402
|
-
console.error("\uD83E\uDDE9 VoiceSDK v2: run_partner_script threw partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(_elapsedMs, "ms):"),
|
|
28853
|
+
console.error("\uD83E\uDDE9 VoiceSDK v2: run_partner_script threw partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(_elapsedMs, "ms):"), _t4);
|
|
28403
28854
|
this.sendMessage({
|
|
28404
28855
|
t: 'run_partner_script_result',
|
|
28405
28856
|
requestId: requestId,
|
|
28406
28857
|
partnerId: partnerId,
|
|
28407
28858
|
action: action,
|
|
28408
28859
|
ok: false,
|
|
28409
|
-
error:
|
|
28860
|
+
error: _t4 && _t4.message || String(_t4)
|
|
28410
28861
|
});
|
|
28411
28862
|
case 7:
|
|
28412
|
-
return
|
|
28863
|
+
return _context5.a(2);
|
|
28413
28864
|
}
|
|
28414
|
-
},
|
|
28865
|
+
}, _callee5, this, [[4, 6]]);
|
|
28415
28866
|
}));
|
|
28416
|
-
function _handleRunPartnerScript(
|
|
28867
|
+
function _handleRunPartnerScript(_x3) {
|
|
28417
28868
|
return _handleRunPartnerScript2.apply(this, arguments);
|
|
28418
28869
|
}
|
|
28419
28870
|
return _handleRunPartnerScript;
|
|
@@ -28458,7 +28909,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28458
28909
|
}, {
|
|
28459
28910
|
key: "injectData",
|
|
28460
28911
|
value: (function () {
|
|
28461
|
-
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28912
|
+
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
28462
28913
|
var _this7 = this;
|
|
28463
28914
|
var options,
|
|
28464
28915
|
trimmedData,
|
|
@@ -28469,15 +28920,15 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28469
28920
|
timeout,
|
|
28470
28921
|
source,
|
|
28471
28922
|
message,
|
|
28472
|
-
|
|
28473
|
-
return _regenerator().w(function (
|
|
28474
|
-
while (1) switch (
|
|
28923
|
+
_args6 = arguments;
|
|
28924
|
+
return _regenerator().w(function (_context6) {
|
|
28925
|
+
while (1) switch (_context6.n) {
|
|
28475
28926
|
case 0:
|
|
28476
|
-
options =
|
|
28927
|
+
options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
|
|
28477
28928
|
// Validation: data content
|
|
28478
28929
|
trimmedData = data === null || data === void 0 ? void 0 : data.trim();
|
|
28479
28930
|
if (trimmedData) {
|
|
28480
|
-
|
|
28931
|
+
_context6.n = 1;
|
|
28481
28932
|
break;
|
|
28482
28933
|
}
|
|
28483
28934
|
error = {
|
|
@@ -28489,7 +28940,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28489
28940
|
throw new Error(error.message);
|
|
28490
28941
|
case 1:
|
|
28491
28942
|
if (!(!this.isConnected || !this.websocket)) {
|
|
28492
|
-
|
|
28943
|
+
_context6.n = 2;
|
|
28493
28944
|
break;
|
|
28494
28945
|
}
|
|
28495
28946
|
_error = {
|
|
@@ -28501,7 +28952,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28501
28952
|
throw new Error(_error.message);
|
|
28502
28953
|
case 2:
|
|
28503
28954
|
if (!(trimmedData.length > 5000)) {
|
|
28504
|
-
|
|
28955
|
+
_context6.n = 3;
|
|
28505
28956
|
break;
|
|
28506
28957
|
}
|
|
28507
28958
|
_error2 = {
|
|
@@ -28530,7 +28981,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28530
28981
|
}
|
|
28531
28982
|
|
|
28532
28983
|
// Return Promise that resolves when acknowledgment is received
|
|
28533
|
-
return
|
|
28984
|
+
return _context6.a(2, new Promise(function (_resolve, _reject) {
|
|
28534
28985
|
// Set up timeout
|
|
28535
28986
|
var timeoutId = setTimeout(function () {
|
|
28536
28987
|
// Remove from pending map
|
|
@@ -28581,9 +29032,9 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28581
29032
|
}
|
|
28582
29033
|
}));
|
|
28583
29034
|
}
|
|
28584
|
-
},
|
|
29035
|
+
}, _callee6, this);
|
|
28585
29036
|
}));
|
|
28586
|
-
function injectData(
|
|
29037
|
+
function injectData(_x4) {
|
|
28587
29038
|
return _injectData.apply(this, arguments);
|
|
28588
29039
|
}
|
|
28589
29040
|
return injectData;
|
|
@@ -28713,20 +29164,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28713
29164
|
}, {
|
|
28714
29165
|
key: "handleBinaryMessage",
|
|
28715
29166
|
value: (function () {
|
|
28716
|
-
var _handleBinaryMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28717
|
-
var arrayBuffer, processedAudio, playbackFormat, container, encoding, pcmData, codec, decoded,
|
|
28718
|
-
return _regenerator().w(function (
|
|
28719
|
-
while (1) switch (
|
|
29167
|
+
var _handleBinaryMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(data) {
|
|
29168
|
+
var arrayBuffer, processedAudio, playbackFormat, container, encoding, pcmData, codec, decoded, _t5;
|
|
29169
|
+
return _regenerator().w(function (_context7) {
|
|
29170
|
+
while (1) switch (_context7.p = _context7.n) {
|
|
28720
29171
|
case 0:
|
|
28721
29172
|
if (!(data instanceof Blob)) {
|
|
28722
|
-
|
|
29173
|
+
_context7.n = 2;
|
|
28723
29174
|
break;
|
|
28724
29175
|
}
|
|
28725
|
-
|
|
29176
|
+
_context7.n = 1;
|
|
28726
29177
|
return data.arrayBuffer();
|
|
28727
29178
|
case 1:
|
|
28728
|
-
arrayBuffer =
|
|
28729
|
-
|
|
29179
|
+
arrayBuffer = _context7.v;
|
|
29180
|
+
_context7.n = 3;
|
|
28730
29181
|
break;
|
|
28731
29182
|
case 2:
|
|
28732
29183
|
arrayBuffer = data;
|
|
@@ -28734,21 +29185,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28734
29185
|
// Convert format if needed (before passing to AudioPlayer)
|
|
28735
29186
|
processedAudio = arrayBuffer;
|
|
28736
29187
|
if (!(this.formatConverter && this.formatConverter.needsConversion())) {
|
|
28737
|
-
|
|
29188
|
+
_context7.n = 7;
|
|
28738
29189
|
break;
|
|
28739
29190
|
}
|
|
28740
|
-
|
|
28741
|
-
|
|
29191
|
+
_context7.p = 4;
|
|
29192
|
+
_context7.n = 5;
|
|
28742
29193
|
return this.formatConverter.convert(arrayBuffer);
|
|
28743
29194
|
case 5:
|
|
28744
|
-
processedAudio =
|
|
29195
|
+
processedAudio = _context7.v;
|
|
28745
29196
|
console.log('✅ VoiceSDK v2: Audio converted to requested format');
|
|
28746
|
-
|
|
29197
|
+
_context7.n = 7;
|
|
28747
29198
|
break;
|
|
28748
29199
|
case 6:
|
|
28749
|
-
|
|
28750
|
-
|
|
28751
|
-
console.error('❌ VoiceSDK v2: Format conversion failed:',
|
|
29200
|
+
_context7.p = 6;
|
|
29201
|
+
_t5 = _context7.v;
|
|
29202
|
+
console.error('❌ VoiceSDK v2: Format conversion failed:', _t5);
|
|
28752
29203
|
console.warn(' Using backend format without conversion');
|
|
28753
29204
|
processedAudio = arrayBuffer; // Fall back to original
|
|
28754
29205
|
case 7:
|
|
@@ -28798,11 +29249,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28798
29249
|
this.audioPlayer.playAudio(processedAudio);
|
|
28799
29250
|
}
|
|
28800
29251
|
case 8:
|
|
28801
|
-
return
|
|
29252
|
+
return _context7.a(2);
|
|
28802
29253
|
}
|
|
28803
|
-
},
|
|
29254
|
+
}, _callee7, this, [[4, 6]]);
|
|
28804
29255
|
}));
|
|
28805
|
-
function handleBinaryMessage(
|
|
29256
|
+
function handleBinaryMessage(_x5) {
|
|
28806
29257
|
return _handleBinaryMessage.apply(this, arguments);
|
|
28807
29258
|
}
|
|
28808
29259
|
return handleBinaryMessage;
|
|
@@ -28990,22 +29441,22 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28990
29441
|
}, {
|
|
28991
29442
|
key: "startRecording",
|
|
28992
29443
|
value: (function () {
|
|
28993
|
-
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29444
|
+
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
28994
29445
|
var existingMediaStream,
|
|
28995
29446
|
error,
|
|
28996
29447
|
_error4,
|
|
28997
29448
|
_error5,
|
|
28998
29449
|
permissionError,
|
|
28999
|
-
|
|
29000
|
-
|
|
29001
|
-
|
|
29002
|
-
|
|
29003
|
-
return _regenerator().w(function (
|
|
29004
|
-
while (1) switch (
|
|
29450
|
+
_args8 = arguments,
|
|
29451
|
+
_t6,
|
|
29452
|
+
_t7,
|
|
29453
|
+
_t8;
|
|
29454
|
+
return _regenerator().w(function (_context8) {
|
|
29455
|
+
while (1) switch (_context8.p = _context8.n) {
|
|
29005
29456
|
case 0:
|
|
29006
|
-
existingMediaStream =
|
|
29457
|
+
existingMediaStream = _args8.length > 0 && _args8[0] !== undefined ? _args8[0] : null;
|
|
29007
29458
|
if (this.isConnected) {
|
|
29008
|
-
|
|
29459
|
+
_context8.n = 1;
|
|
29009
29460
|
break;
|
|
29010
29461
|
}
|
|
29011
29462
|
error = new Error('Not connected to voice server');
|
|
@@ -29013,14 +29464,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29013
29464
|
throw error;
|
|
29014
29465
|
case 1:
|
|
29015
29466
|
if (!this.isRecording) {
|
|
29016
|
-
|
|
29467
|
+
_context8.n = 2;
|
|
29017
29468
|
break;
|
|
29018
29469
|
}
|
|
29019
29470
|
console.warn('VoiceSDK v2: Already recording');
|
|
29020
|
-
return
|
|
29471
|
+
return _context8.a(2, true);
|
|
29021
29472
|
case 2:
|
|
29022
29473
|
if (!this.disclaimersPending) {
|
|
29023
|
-
|
|
29474
|
+
_context8.n = 3;
|
|
29024
29475
|
break;
|
|
29025
29476
|
}
|
|
29026
29477
|
_error4 = new Error('Server disclaimers must be accepted before recording. Call sendDisclaimerAck(true) first.');
|
|
@@ -29029,28 +29480,28 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29029
29480
|
throw _error4;
|
|
29030
29481
|
case 3:
|
|
29031
29482
|
console.log('🎤 VoiceSDK v2: Starting recording...');
|
|
29032
|
-
|
|
29483
|
+
_context8.p = 4;
|
|
29033
29484
|
// CRITICAL for mobile browsers: Request microphone permission FIRST
|
|
29034
29485
|
// iOS: Pass existingMediaStream to avoid second getUserMedia (can fail on iOS)
|
|
29035
29486
|
console.log('🎤 VoiceSDK v2: Requesting microphone permission (mobile-friendly)...');
|
|
29036
|
-
|
|
29487
|
+
_context8.n = 5;
|
|
29037
29488
|
return this.audioRecorder.start(existingMediaStream ? {
|
|
29038
29489
|
existingMediaStream: existingMediaStream
|
|
29039
29490
|
} : {});
|
|
29040
29491
|
case 5:
|
|
29041
29492
|
if (!(!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN)) {
|
|
29042
|
-
|
|
29493
|
+
_context8.n = 10;
|
|
29043
29494
|
break;
|
|
29044
29495
|
}
|
|
29045
|
-
|
|
29046
|
-
|
|
29496
|
+
_context8.p = 6;
|
|
29497
|
+
_context8.n = 7;
|
|
29047
29498
|
return this.audioRecorder.stop();
|
|
29048
29499
|
case 7:
|
|
29049
|
-
|
|
29500
|
+
_context8.n = 9;
|
|
29050
29501
|
break;
|
|
29051
29502
|
case 8:
|
|
29052
|
-
|
|
29053
|
-
|
|
29503
|
+
_context8.p = 8;
|
|
29504
|
+
_t6 = _context8.v;
|
|
29054
29505
|
case 9:
|
|
29055
29506
|
_error5 = new Error('Connection lost - server may have rejected the call');
|
|
29056
29507
|
_error5.name = 'ServerRejected';
|
|
@@ -29059,7 +29510,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29059
29510
|
// The error handler in VoiceInterface will handle it appropriately
|
|
29060
29511
|
throw _error5;
|
|
29061
29512
|
case 10:
|
|
29062
|
-
|
|
29513
|
+
_context8.n = 11;
|
|
29063
29514
|
return this.audioPlayer.resumeAudioContext();
|
|
29064
29515
|
case 11:
|
|
29065
29516
|
// After permission is granted, send start_continuous_mode message to server
|
|
@@ -29070,45 +29521,45 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29070
29521
|
|
|
29071
29522
|
// Request screen wake lock to keep screen on during voice call (mobile)
|
|
29072
29523
|
this._requestWakeLock();
|
|
29073
|
-
return
|
|
29524
|
+
return _context8.a(2, true);
|
|
29074
29525
|
case 12:
|
|
29075
|
-
|
|
29076
|
-
|
|
29526
|
+
_context8.p = 12;
|
|
29527
|
+
_t7 = _context8.v;
|
|
29077
29528
|
if (!(this.audioRecorder && this.audioRecorder.isRecording)) {
|
|
29078
|
-
|
|
29529
|
+
_context8.n = 16;
|
|
29079
29530
|
break;
|
|
29080
29531
|
}
|
|
29081
|
-
|
|
29082
|
-
|
|
29532
|
+
_context8.p = 13;
|
|
29533
|
+
_context8.n = 14;
|
|
29083
29534
|
return this.audioRecorder.stop();
|
|
29084
29535
|
case 14:
|
|
29085
|
-
|
|
29536
|
+
_context8.n = 16;
|
|
29086
29537
|
break;
|
|
29087
29538
|
case 15:
|
|
29088
|
-
|
|
29089
|
-
|
|
29539
|
+
_context8.p = 15;
|
|
29540
|
+
_t8 = _context8.v;
|
|
29090
29541
|
case 16:
|
|
29091
|
-
if (!(
|
|
29092
|
-
|
|
29542
|
+
if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
|
|
29543
|
+
_context8.n = 17;
|
|
29093
29544
|
break;
|
|
29094
29545
|
}
|
|
29095
|
-
return
|
|
29546
|
+
return _context8.a(2, false);
|
|
29096
29547
|
case 17:
|
|
29097
29548
|
// Log and emit other errors (permission denied, etc.)
|
|
29098
|
-
console.error('❌ VoiceSDK v2: Failed to start recording:',
|
|
29549
|
+
console.error('❌ VoiceSDK v2: Failed to start recording:', _t7);
|
|
29099
29550
|
|
|
29100
29551
|
// Provide helpful error messages for permission issues
|
|
29101
|
-
if (
|
|
29552
|
+
if (_t7.name === 'NotAllowedError' || _t7.name === 'PermissionDeniedError') {
|
|
29102
29553
|
permissionError = new Error('Microphone permission denied. Please allow microphone access in your browser settings and try again.');
|
|
29103
|
-
permissionError.name =
|
|
29104
|
-
permissionError.originalError =
|
|
29554
|
+
permissionError.name = _t7.name;
|
|
29555
|
+
permissionError.originalError = _t7;
|
|
29105
29556
|
this.emit('error', permissionError);
|
|
29106
29557
|
} else {
|
|
29107
|
-
this.emit('error',
|
|
29558
|
+
this.emit('error', _t7);
|
|
29108
29559
|
}
|
|
29109
|
-
return
|
|
29560
|
+
return _context8.a(2, false);
|
|
29110
29561
|
}
|
|
29111
|
-
},
|
|
29562
|
+
}, _callee8, this, [[13, 15], [6, 8], [4, 12]]);
|
|
29112
29563
|
}));
|
|
29113
29564
|
function startRecording() {
|
|
29114
29565
|
return _startRecording.apply(this, arguments);
|
|
@@ -29122,20 +29573,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29122
29573
|
}, {
|
|
29123
29574
|
key: "stopRecording",
|
|
29124
29575
|
value: (function () {
|
|
29125
|
-
var _stopRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29126
|
-
var
|
|
29127
|
-
return _regenerator().w(function (
|
|
29128
|
-
while (1) switch (
|
|
29576
|
+
var _stopRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
29577
|
+
var _t9;
|
|
29578
|
+
return _regenerator().w(function (_context9) {
|
|
29579
|
+
while (1) switch (_context9.p = _context9.n) {
|
|
29129
29580
|
case 0:
|
|
29130
29581
|
if (this.isRecording) {
|
|
29131
|
-
|
|
29582
|
+
_context9.n = 1;
|
|
29132
29583
|
break;
|
|
29133
29584
|
}
|
|
29134
29585
|
console.warn('VoiceSDK v2: Not recording');
|
|
29135
|
-
return
|
|
29586
|
+
return _context9.a(2, true);
|
|
29136
29587
|
case 1:
|
|
29137
29588
|
console.log('🛑 VoiceSDK v2: Stopping recording...');
|
|
29138
|
-
|
|
29589
|
+
_context9.p = 2;
|
|
29139
29590
|
// Send stop_continuous_mode message to server
|
|
29140
29591
|
|
|
29141
29592
|
this.sendMessage({
|
|
@@ -29153,21 +29604,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29153
29604
|
this._releaseWakeLock();
|
|
29154
29605
|
|
|
29155
29606
|
// Stop capturing audio from microphone
|
|
29156
|
-
|
|
29607
|
+
_context9.n = 3;
|
|
29157
29608
|
return this.audioRecorder.stop();
|
|
29158
29609
|
case 3:
|
|
29159
29610
|
// Stop any playing audio
|
|
29160
29611
|
|
|
29161
29612
|
this.stopAudioPlayback();
|
|
29162
|
-
return
|
|
29613
|
+
return _context9.a(2, true);
|
|
29163
29614
|
case 4:
|
|
29164
|
-
|
|
29165
|
-
|
|
29166
|
-
console.error('VoiceSDK v2: Error stopping recording:',
|
|
29167
|
-
this.emit('error',
|
|
29168
|
-
return
|
|
29615
|
+
_context9.p = 4;
|
|
29616
|
+
_t9 = _context9.v;
|
|
29617
|
+
console.error('VoiceSDK v2: Error stopping recording:', _t9);
|
|
29618
|
+
this.emit('error', _t9);
|
|
29619
|
+
return _context9.a(2, false);
|
|
29169
29620
|
}
|
|
29170
|
-
},
|
|
29621
|
+
}, _callee9, this, [[2, 4]]);
|
|
29171
29622
|
}));
|
|
29172
29623
|
function stopRecording() {
|
|
29173
29624
|
return _stopRecording.apply(this, arguments);
|
|
@@ -29181,27 +29632,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29181
29632
|
}, {
|
|
29182
29633
|
key: "toggleRecording",
|
|
29183
29634
|
value: (function () {
|
|
29184
|
-
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29185
|
-
return _regenerator().w(function (
|
|
29186
|
-
while (1) switch (
|
|
29635
|
+
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
29636
|
+
return _regenerator().w(function (_context0) {
|
|
29637
|
+
while (1) switch (_context0.n) {
|
|
29187
29638
|
case 0:
|
|
29188
29639
|
if (!this.isRecording) {
|
|
29189
|
-
|
|
29640
|
+
_context0.n = 2;
|
|
29190
29641
|
break;
|
|
29191
29642
|
}
|
|
29192
|
-
|
|
29643
|
+
_context0.n = 1;
|
|
29193
29644
|
return this.stopRecording();
|
|
29194
29645
|
case 1:
|
|
29195
|
-
return
|
|
29646
|
+
return _context0.a(2, _context0.v);
|
|
29196
29647
|
case 2:
|
|
29197
|
-
|
|
29648
|
+
_context0.n = 3;
|
|
29198
29649
|
return this.startRecording();
|
|
29199
29650
|
case 3:
|
|
29200
|
-
return
|
|
29651
|
+
return _context0.a(2, _context0.v);
|
|
29201
29652
|
case 4:
|
|
29202
|
-
return
|
|
29653
|
+
return _context0.a(2);
|
|
29203
29654
|
}
|
|
29204
|
-
},
|
|
29655
|
+
}, _callee0, this);
|
|
29205
29656
|
}));
|
|
29206
29657
|
function toggleRecording() {
|
|
29207
29658
|
return _toggleRecording.apply(this, arguments);
|
|
@@ -29232,33 +29683,33 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29232
29683
|
}, {
|
|
29233
29684
|
key: "_requestWakeLock",
|
|
29234
29685
|
value: (function () {
|
|
29235
|
-
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29686
|
+
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
|
|
29236
29687
|
var _this9 = this;
|
|
29237
|
-
var
|
|
29238
|
-
return _regenerator().w(function (
|
|
29239
|
-
while (1) switch (
|
|
29688
|
+
var _t0;
|
|
29689
|
+
return _regenerator().w(function (_context1) {
|
|
29690
|
+
while (1) switch (_context1.p = _context1.n) {
|
|
29240
29691
|
case 0:
|
|
29241
29692
|
if ('wakeLock' in navigator) {
|
|
29242
|
-
|
|
29693
|
+
_context1.n = 1;
|
|
29243
29694
|
break;
|
|
29244
29695
|
}
|
|
29245
29696
|
console.log('📱 VoiceSDK v2: Wake Lock API not available in this browser');
|
|
29246
|
-
return
|
|
29697
|
+
return _context1.a(2);
|
|
29247
29698
|
case 1:
|
|
29248
29699
|
if (!(this.wakeLock !== null || this._wakeLockRequesting)) {
|
|
29249
|
-
|
|
29700
|
+
_context1.n = 2;
|
|
29250
29701
|
break;
|
|
29251
29702
|
}
|
|
29252
29703
|
console.log('📱 VoiceSDK v2: Wake lock already active or being requested');
|
|
29253
|
-
return
|
|
29704
|
+
return _context1.a(2);
|
|
29254
29705
|
case 2:
|
|
29255
|
-
|
|
29706
|
+
_context1.p = 2;
|
|
29256
29707
|
this._wakeLockRequesting = true;
|
|
29257
29708
|
// Request wake lock (screen type keeps screen on)
|
|
29258
|
-
|
|
29709
|
+
_context1.n = 3;
|
|
29259
29710
|
return navigator.wakeLock.request('screen');
|
|
29260
29711
|
case 3:
|
|
29261
|
-
this.wakeLock =
|
|
29712
|
+
this.wakeLock = _context1.v;
|
|
29262
29713
|
console.log('📱 VoiceSDK v2: Screen wake lock activated - screen will stay on during call');
|
|
29263
29714
|
|
|
29264
29715
|
// Handle wake lock release (e.g., user switches tabs, locks device)
|
|
@@ -29266,23 +29717,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29266
29717
|
console.log('📱 VoiceSDK v2: Wake lock released by system');
|
|
29267
29718
|
_this9.wakeLock = null;
|
|
29268
29719
|
});
|
|
29269
|
-
|
|
29720
|
+
_context1.n = 5;
|
|
29270
29721
|
break;
|
|
29271
29722
|
case 4:
|
|
29272
|
-
|
|
29273
|
-
|
|
29723
|
+
_context1.p = 4;
|
|
29724
|
+
_t0 = _context1.v;
|
|
29274
29725
|
// Wake lock request failed (e.g., permission denied, battery saver mode)
|
|
29275
|
-
console.warn('📱 VoiceSDK v2: Failed to request wake lock:',
|
|
29726
|
+
console.warn('📱 VoiceSDK v2: Failed to request wake lock:', _t0.message);
|
|
29276
29727
|
this.wakeLock = null;
|
|
29277
29728
|
// Don't throw - this is a nice-to-have feature, not critical
|
|
29278
29729
|
case 5:
|
|
29279
|
-
|
|
29730
|
+
_context1.p = 5;
|
|
29280
29731
|
this._wakeLockRequesting = false;
|
|
29281
|
-
return
|
|
29732
|
+
return _context1.f(5);
|
|
29282
29733
|
case 6:
|
|
29283
|
-
return
|
|
29734
|
+
return _context1.a(2);
|
|
29284
29735
|
}
|
|
29285
|
-
},
|
|
29736
|
+
}, _callee1, this, [[2, 4, 5, 6]]);
|
|
29286
29737
|
}));
|
|
29287
29738
|
function _requestWakeLock() {
|
|
29288
29739
|
return _requestWakeLock2.apply(this, arguments);
|
|
@@ -29297,34 +29748,34 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29297
29748
|
}, {
|
|
29298
29749
|
key: "_releaseWakeLock",
|
|
29299
29750
|
value: (function () {
|
|
29300
|
-
var _releaseWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29301
|
-
var
|
|
29302
|
-
return _regenerator().w(function (
|
|
29303
|
-
while (1) switch (
|
|
29751
|
+
var _releaseWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
|
|
29752
|
+
var _t1;
|
|
29753
|
+
return _regenerator().w(function (_context10) {
|
|
29754
|
+
while (1) switch (_context10.p = _context10.n) {
|
|
29304
29755
|
case 0:
|
|
29305
29756
|
if (!(this.wakeLock === null)) {
|
|
29306
|
-
|
|
29757
|
+
_context10.n = 1;
|
|
29307
29758
|
break;
|
|
29308
29759
|
}
|
|
29309
|
-
return
|
|
29760
|
+
return _context10.a(2);
|
|
29310
29761
|
case 1:
|
|
29311
|
-
|
|
29312
|
-
|
|
29762
|
+
_context10.p = 1;
|
|
29763
|
+
_context10.n = 2;
|
|
29313
29764
|
return this.wakeLock.release();
|
|
29314
29765
|
case 2:
|
|
29315
29766
|
this.wakeLock = null;
|
|
29316
29767
|
console.log('📱 VoiceSDK v2: Screen wake lock released');
|
|
29317
|
-
|
|
29768
|
+
_context10.n = 4;
|
|
29318
29769
|
break;
|
|
29319
29770
|
case 3:
|
|
29320
|
-
|
|
29321
|
-
|
|
29322
|
-
console.warn('📱 VoiceSDK v2: Error releasing wake lock:',
|
|
29771
|
+
_context10.p = 3;
|
|
29772
|
+
_t1 = _context10.v;
|
|
29773
|
+
console.warn('📱 VoiceSDK v2: Error releasing wake lock:', _t1.message);
|
|
29323
29774
|
this.wakeLock = null;
|
|
29324
29775
|
case 4:
|
|
29325
|
-
return
|
|
29776
|
+
return _context10.a(2);
|
|
29326
29777
|
}
|
|
29327
|
-
},
|
|
29778
|
+
}, _callee10, this, [[1, 3]]);
|
|
29328
29779
|
}));
|
|
29329
29780
|
function _releaseWakeLock() {
|
|
29330
29781
|
return _releaseWakeLock2.apply(this, arguments);
|
|
@@ -29348,21 +29799,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29348
29799
|
}, {
|
|
29349
29800
|
key: "handleBargeIn",
|
|
29350
29801
|
value: (function () {
|
|
29351
|
-
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29352
|
-
return _regenerator().w(function (
|
|
29353
|
-
while (1) switch (
|
|
29802
|
+
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
|
|
29803
|
+
return _regenerator().w(function (_context11) {
|
|
29804
|
+
while (1) switch (_context11.n) {
|
|
29354
29805
|
case 0:
|
|
29355
29806
|
this.stopAudioPlayback();
|
|
29356
29807
|
if (this.isRecording) {
|
|
29357
|
-
|
|
29808
|
+
_context11.n = 1;
|
|
29358
29809
|
break;
|
|
29359
29810
|
}
|
|
29360
|
-
|
|
29811
|
+
_context11.n = 1;
|
|
29361
29812
|
return this.startRecording();
|
|
29362
29813
|
case 1:
|
|
29363
|
-
return
|
|
29814
|
+
return _context11.a(2);
|
|
29364
29815
|
}
|
|
29365
|
-
},
|
|
29816
|
+
}, _callee11, this);
|
|
29366
29817
|
}));
|
|
29367
29818
|
function handleBargeIn() {
|
|
29368
29819
|
return _handleBargeIn.apply(this, arguments);
|
|
@@ -32275,10 +32726,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32275
32726
|
this._flavorObj = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
32276
32727
|
if (this._flavorObj && this._flavorObj.type) {
|
|
32277
32728
|
this._initFlavor(this._flavorObj.type);
|
|
32278
|
-
|
|
32279
|
-
|
|
32729
|
+
} else if (this._flavorObj && !this._flavorObj.type && this._flavorObj.callView !== 'minimized') {
|
|
32730
|
+
// A flavor object with neither a "type" nor callView:'minimized' is malformed.
|
|
32731
|
+
// (callView:'minimized' alone is a valid flavor-less minimized-strip config.)
|
|
32280
32732
|
console.error('[TTPChatWidget] flavor object is set but missing required "type" field. Widget will run in vanilla mode.');
|
|
32281
32733
|
}
|
|
32734
|
+
// The desktop minimized bottom strip is flavor-independent: it only needs
|
|
32735
|
+
// flavor.callView === 'minimized' (+ desktop width). Init it regardless of
|
|
32736
|
+
// whether a flavor type is present, so callView:'minimized' works standalone
|
|
32737
|
+
// with no partner/flavor. _initEcommerceVoiceStrip() self-guards and no-ops
|
|
32738
|
+
// when callView !== 'minimized' or on mobile.
|
|
32739
|
+
this._initEcommerceVoiceStrip();
|
|
32282
32740
|
}
|
|
32283
32741
|
|
|
32284
32742
|
/**
|
|
@@ -32694,7 +33152,11 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32694
33152
|
offset: positionConfig.offset || {
|
|
32695
33153
|
x: 20,
|
|
32696
33154
|
y: 20
|
|
32697
|
-
}
|
|
33155
|
+
},
|
|
33156
|
+
// When true, the launcher pill / mobile FAB can be dragged around the
|
|
33157
|
+
// viewport. Set position.draggablePersist:false to reset position each load.
|
|
33158
|
+
draggable: false,
|
|
33159
|
+
draggablePersist: true
|
|
32698
33160
|
}, _typeof(userConfig.position) === 'object' ? userConfig.position : {}),
|
|
32699
33161
|
// Button Configuration
|
|
32700
33162
|
button: _objectSpread({
|
|
@@ -33330,6 +33792,125 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33330
33792
|
var footer = (_root$querySelector = root.querySelector) === null || _root$querySelector === void 0 ? void 0 : _root$querySelector.call(root, '.ttp-footer');
|
|
33331
33793
|
if (footer) footer.style.display = visible ? '' : 'none';
|
|
33332
33794
|
}
|
|
33795
|
+
|
|
33796
|
+
/**
|
|
33797
|
+
* Resolve the most recent conversation id used by either channel.
|
|
33798
|
+
* Prefers a live voice/text SDK value, then falls back to persisted state.
|
|
33799
|
+
* @returns {string|null}
|
|
33800
|
+
*/
|
|
33801
|
+
}, {
|
|
33802
|
+
key: "_getLastConversationId",
|
|
33803
|
+
value: function _getLastConversationId() {
|
|
33804
|
+
var _this$voiceInterface3, _this$sdk;
|
|
33805
|
+
var live = (_this$voiceInterface3 = this.voiceInterface) === null || _this$voiceInterface3 === void 0 || (_this$voiceInterface3 = _this$voiceInterface3.sdk) === null || _this$voiceInterface3 === void 0 || (_this$voiceInterface3 = _this$voiceInterface3.voiceSDK) === null || _this$voiceInterface3 === void 0 ? void 0 : _this$voiceInterface3.conversationId;
|
|
33806
|
+
if (live) return live;
|
|
33807
|
+
var textId = (_this$sdk = this.sdk) === null || _this$sdk === void 0 || (_this$sdk = _this$sdk.config) === null || _this$sdk === void 0 ? void 0 : _this$sdk.conversationId;
|
|
33808
|
+
if (textId) return textId;
|
|
33809
|
+
try {
|
|
33810
|
+
var raw = sessionStorage.getItem('voice_resume_state');
|
|
33811
|
+
if (raw) {
|
|
33812
|
+
var s = JSON.parse(raw);
|
|
33813
|
+
if (s && s.conversationId) return s.conversationId;
|
|
33814
|
+
}
|
|
33815
|
+
} catch (_) {/* ignore */}
|
|
33816
|
+
try {
|
|
33817
|
+
var t = localStorage.getItem('ttp_text_chat_conversation_id');
|
|
33818
|
+
if (t) return t;
|
|
33819
|
+
} catch (_) {/* ignore */}
|
|
33820
|
+
return null;
|
|
33821
|
+
}
|
|
33822
|
+
|
|
33823
|
+
/** Inline TalkToPC logo mark (speech bubble + sound waves). */
|
|
33824
|
+
}, {
|
|
33825
|
+
key: "_aboutLogoSVG",
|
|
33826
|
+
value: function _aboutLogoSVG() {
|
|
33827
|
+
return "<svg class=\"ttp-about-logo-mark\" width=\"34\" height=\"34\" viewBox=\"0 0 48 48\" fill=\"none\" aria-hidden=\"true\">\n <rect x=\"4\" y=\"6\" width=\"40\" height=\"30\" rx=\"10\" fill=\"url(#ttpAboutGrad)\"/>\n <path d=\"M16 36l-4 7 11-7z\" fill=\"url(#ttpAboutGrad)\"/>\n <g stroke=\"#ffffff\" stroke-width=\"2.6\" stroke-linecap=\"round\">\n <line x1=\"18\" y1=\"17\" x2=\"18\" y2=\"25\"/>\n <line x1=\"24\" y1=\"13\" x2=\"24\" y2=\"29\"/>\n <line x1=\"30\" y1=\"18\" x2=\"30\" y2=\"24\"/>\n </g>\n <defs>\n <linearGradient id=\"ttpAboutGrad\" x1=\"4\" y1=\"6\" x2=\"44\" y2=\"43\" gradientUnits=\"userSpaceOnUse\">\n <stop stop-color=\"#8b5cf6\"/>\n <stop offset=\"1\" stop-color=\"#6d28d9\"/>\n </linearGradient>\n </defs>\n </svg>";
|
|
33828
|
+
}
|
|
33829
|
+
|
|
33830
|
+
/**
|
|
33831
|
+
* Inject the "About" dialog styles into document.head once.
|
|
33832
|
+
* Global (light DOM) so the dialog renders above the desktop minimized strip,
|
|
33833
|
+
* which lives outside the shadow root at the maximum z-index.
|
|
33834
|
+
*/
|
|
33835
|
+
}, {
|
|
33836
|
+
key: "_ensureAboutStyles",
|
|
33837
|
+
value: function _ensureAboutStyles() {
|
|
33838
|
+
if (document.getElementById('ttp-about-dialog-styles')) return;
|
|
33839
|
+
var style = document.createElement('style');
|
|
33840
|
+
style.id = 'ttp-about-dialog-styles';
|
|
33841
|
+
style.textContent = "\n .ttp-about-overlay {\n position: fixed; inset: 0; z-index: 2147483647;\n display: flex; align-items: center; justify-content: center;\n padding: 16px; box-sizing: border-box;\n background: rgba(15,15,25,0.55);\n backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);\n animation: ttpAboutFade 0.18s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n }\n @keyframes ttpAboutFade { from { opacity: 0; } to { opacity: 1; } }\n .ttp-about-card {\n position: relative; width: 100%; max-width: 320px; box-sizing: border-box;\n background: #ffffff; color: #1f2937; border-radius: 16px;\n padding: 24px 22px 22px; box-shadow: 0 24px 60px rgba(0,0,0,0.35);\n text-align: center; animation: ttpAboutPop 0.2s ease-out;\n }\n @keyframes ttpAboutPop {\n from { transform: translateY(8px) scale(0.98); opacity: 0; }\n to { transform: translateY(0) scale(1); opacity: 1; }\n }\n .ttp-about-close {\n position: absolute; top: 10px; inset-inline-end: 10px;\n background: none; border: none; cursor: pointer; color: #9ca3af;\n padding: 6px; line-height: 0; border-radius: 50%;\n transition: background 0.2s, color 0.2s;\n }\n .ttp-about-close:hover { background: #f3f4f6; color: #4b5563; }\n .ttp-about-logo {\n display: flex; align-items: center; justify-content: center;\n gap: 8px; margin-bottom: 14px;\n }\n .ttp-about-logo-mark { display: block; flex-shrink: 0; }\n .ttp-about-brand {\n font-size: 20px; font-weight: 800; letter-spacing: -0.2px; color: #6d28d9;\n }\n .ttp-about-title {\n font-size: 13px; font-weight: 600; text-transform: uppercase;\n letter-spacing: 1px; color: #9ca3af; margin-bottom: 16px;\n }\n .ttp-about-rows {\n display: flex; flex-direction: column; gap: 10px; text-align: start;\n }\n .ttp-about-row {\n display: flex; flex-direction: column; gap: 3px;\n background: #f9fafb; border: 1px solid #f0f0f4;\n border-radius: 10px; padding: 10px 12px;\n }\n .ttp-about-key {\n font-size: 11px; font-weight: 600; text-transform: uppercase;\n letter-spacing: 0.5px; color: #9ca3af;\n }\n .ttp-about-val {\n font-size: 14px; font-weight: 600; color: #1f2937; word-break: break-all;\n }\n .ttp-about-mono {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12.5px; font-weight: 500;\n }\n .ttp-about-muted { color: #9ca3af; font-weight: 500; font-style: italic; }\n ";
|
|
33842
|
+
document.head.appendChild(style);
|
|
33843
|
+
}
|
|
33844
|
+
|
|
33845
|
+
/** Open the shared "About" dialog (logo + SDK version + last conversation id). */
|
|
33846
|
+
}, {
|
|
33847
|
+
key: "_openAboutModal",
|
|
33848
|
+
value: function _openAboutModal() {
|
|
33849
|
+
var _this8 = this,
|
|
33850
|
+
_overlay$querySelecto;
|
|
33851
|
+
// Toggle: if already open, close it.
|
|
33852
|
+
if (this._aboutOverlay) {
|
|
33853
|
+
this._closeAboutModal();
|
|
33854
|
+
return;
|
|
33855
|
+
}
|
|
33856
|
+
this._ensureAboutStyles();
|
|
33857
|
+
var version = true ? "2.45.14" : 0;
|
|
33858
|
+
var convId = this._getLastConversationId();
|
|
33859
|
+
var t = function t(k, fb) {
|
|
33860
|
+
try {
|
|
33861
|
+
var _this8$voiceInterface, _this8$voiceInterface2, _this8$textInterface, _this8$textInterface$;
|
|
33862
|
+
return ((_this8$voiceInterface = _this8.voiceInterface) === null || _this8$voiceInterface === void 0 || (_this8$voiceInterface2 = _this8$voiceInterface.t) === null || _this8$voiceInterface2 === void 0 ? void 0 : _this8$voiceInterface2.call(_this8$voiceInterface, k)) || ((_this8$textInterface = _this8.textInterface) === null || _this8$textInterface === void 0 || (_this8$textInterface$ = _this8$textInterface.t) === null || _this8$textInterface$ === void 0 ? void 0 : _this8$textInterface$.call(_this8$textInterface, k)) || fb;
|
|
33863
|
+
} catch (_) {
|
|
33864
|
+
return fb;
|
|
33865
|
+
}
|
|
33866
|
+
};
|
|
33867
|
+
var title = t('aboutTitle', 'About');
|
|
33868
|
+
var versionLabel = t('aboutVersion', 'SDK version');
|
|
33869
|
+
var convLabel = t('aboutConversationId', 'Last conversation ID');
|
|
33870
|
+
var noneLabel = t('aboutNoConversation', 'No conversation yet');
|
|
33871
|
+
var overlay = document.createElement('div');
|
|
33872
|
+
overlay.className = 'ttp-about-overlay';
|
|
33873
|
+
overlay.innerHTML = "\n <div class=\"ttp-about-card\" role=\"dialog\" aria-modal=\"true\" aria-label=\"".concat(title, "\">\n <button type=\"button\" class=\"ttp-about-close\" aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 12 12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <path d=\"M10 2L2 10M2 2l8 8\"/>\n </svg>\n </button>\n <div class=\"ttp-about-logo\">").concat(this._aboutLogoSVG(), "<span class=\"ttp-about-brand\">TalkToPC</span></div>\n <div class=\"ttp-about-title\">").concat(title, "</div>\n <div class=\"ttp-about-rows\">\n <div class=\"ttp-about-row\">\n <span class=\"ttp-about-key\">").concat(versionLabel, "</span>\n <span class=\"ttp-about-val\" data-about-version></span>\n </div>\n <div class=\"ttp-about-row\">\n <span class=\"ttp-about-key\">").concat(convLabel, "</span>\n <span class=\"ttp-about-val ttp-about-mono\" data-about-conv></span>\n </div>\n </div>\n </div>");
|
|
33874
|
+
|
|
33875
|
+
// Fill dynamic values via textContent to avoid any injection.
|
|
33876
|
+
var verEl = overlay.querySelector('[data-about-version]');
|
|
33877
|
+
if (verEl) verEl.textContent = version ? "v".concat(version) : '—';
|
|
33878
|
+
var convEl = overlay.querySelector('[data-about-conv]');
|
|
33879
|
+
if (convEl) {
|
|
33880
|
+
convEl.textContent = convId || noneLabel;
|
|
33881
|
+
if (!convId) convEl.classList.add('ttp-about-muted');
|
|
33882
|
+
}
|
|
33883
|
+
var close = function close() {
|
|
33884
|
+
return _this8._closeAboutModal();
|
|
33885
|
+
};
|
|
33886
|
+
overlay.addEventListener('click', function (e) {
|
|
33887
|
+
if (e.target === overlay) close();
|
|
33888
|
+
});
|
|
33889
|
+
(_overlay$querySelecto = overlay.querySelector('.ttp-about-close')) === null || _overlay$querySelecto === void 0 || _overlay$querySelecto.addEventListener('click', function (e) {
|
|
33890
|
+
e.stopPropagation();
|
|
33891
|
+
close();
|
|
33892
|
+
});
|
|
33893
|
+
this._aboutKeyHandler = function (e) {
|
|
33894
|
+
if (e.key === 'Escape') close();
|
|
33895
|
+
};
|
|
33896
|
+
document.addEventListener('keydown', this._aboutKeyHandler);
|
|
33897
|
+
document.body.appendChild(overlay);
|
|
33898
|
+
this._aboutOverlay = overlay;
|
|
33899
|
+
}
|
|
33900
|
+
|
|
33901
|
+
/** Close the "About" dialog if open. */
|
|
33902
|
+
}, {
|
|
33903
|
+
key: "_closeAboutModal",
|
|
33904
|
+
value: function _closeAboutModal() {
|
|
33905
|
+
if (this._aboutKeyHandler) {
|
|
33906
|
+
document.removeEventListener('keydown', this._aboutKeyHandler);
|
|
33907
|
+
this._aboutKeyHandler = null;
|
|
33908
|
+
}
|
|
33909
|
+
if (this._aboutOverlay) {
|
|
33910
|
+
this._aboutOverlay.remove();
|
|
33911
|
+
this._aboutOverlay = null;
|
|
33912
|
+
}
|
|
33913
|
+
}
|
|
33333
33914
|
}, {
|
|
33334
33915
|
key: "generatePositionStyles",
|
|
33335
33916
|
value: function generatePositionStyles() {
|
|
@@ -33461,13 +34042,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33461
34042
|
var callActivePanelBg = callSurfaceGradient;
|
|
33462
34043
|
var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
|
|
33463
34044
|
var voiceActiveVisibleSelector = '#voiceInterface.active #voiceActiveState:not([style*="display: none"]):not([style*="display:none"])';
|
|
33464
|
-
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 right: 10px !important;\n left: auto !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 20px) !important;\n height: auto !important;\n max-height: calc(100vh - 130px) !important;\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 right: 8px !important;\n left: auto !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 16px) !important;\n height: auto !important;\n max-height: calc(100vh - 120px) !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 /* Shared panel chrome; size/position differ \u2014 desktop card vs mobile sheet (see @media blocks earlier) */\n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").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 opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n /* Desktop / tablet: floating 340px card anchored to launcher */\n @media (min-width: 769px) {\n #text-chat-panel {\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 transform-origin: bottom right").concat(important, ";\n }\n /* Text chat: fixed height so the message list scrolls instead of growing the panel per message */\n #text-chat-panel:has(.text-interface.active) {\n height: min(520px, calc(100vh - 100px))").concat(important, ";\n }\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 ").concat(textUsesVoiceTheme ? "\n /* Text chat with voice theme: same hero surface as voice idle; inner shells transparent */\n #text-chat-panel.open:has(.text-interface.active) {\n background: ".concat(callSurfaceGradient).concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .widget-shell,\n #text-chat-panel.open:has(.text-interface.active) .panel-inner,\n #text-chat-panel.open:has(.text-interface.active) .widget-container {\n background: transparent").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer span {\n color: rgba(255,255,255,0.35)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer a {\n color: ").concat(footerLinkOnDarkHero).concat(important, ";\n }\n ") : '', "\n \n /* Voice may scroll as a whole; text chat keeps a fixed shell and scrolls #messagesContainer only */\n #text-chat-panel .widget-container > .voice-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, ";\n }\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n overflow-x: visible").concat(important, ";\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 ");
|
|
34045
|
+
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 right: 10px !important;\n left: auto !important;\n bottom: 92px !important; /* 56px button + 20px gap + 16px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 20px) !important;\n height: auto !important;\n max-height: calc(100vh - 130px) !important;\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 right: 8px !important;\n left: auto !important;\n bottom: 86px !important; /* 54px button + 20px gap + 12px footer */\n top: auto !important;\n width: 340px !important;\n max-width: calc(100vw - 16px) !important;\n height: auto !important;\n max-height: calc(100vh - 120px) !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 /* Shared panel chrome; size/position differ \u2014 desktop card vs mobile sheet (see @media blocks earlier) */\n #text-chat-panel {\n display: none").concat(important, ";\n position: fixed").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 opacity: 0").concat(important, ";\n pointer-events: none").concat(important, ";\n box-sizing: border-box").concat(important, ";\n }\n\n /* Desktop / tablet: floating 340px card anchored to launcher */\n @media (min-width: 769px) {\n #text-chat-panel {\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 transform-origin: bottom right").concat(important, ";\n }\n /* Text chat: fixed height so the message list scrolls instead of growing the panel per message */\n #text-chat-panel:has(.text-interface.active) {\n height: min(520px, calc(100vh - 100px))").concat(important, ";\n }\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 ").concat(textUsesVoiceTheme ? "\n /* Text chat with voice theme: same hero surface as voice idle; inner shells transparent */\n #text-chat-panel.open:has(.text-interface.active) {\n background: ".concat(callSurfaceGradient).concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .widget-shell,\n #text-chat-panel.open:has(.text-interface.active) .panel-inner,\n #text-chat-panel.open:has(.text-interface.active) .widget-container {\n background: transparent").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer {\n background: transparent").concat(important, ";\n border-top-color: rgba(255,255,255,0.06)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer span {\n color: rgba(255,255,255,0.35)").concat(important, ";\n }\n #text-chat-panel.open:has(.text-interface.active) .ttp-footer a {\n color: ").concat(footerLinkOnDarkHero).concat(important, ";\n }\n ") : '', "\n \n /* Voice may scroll as a whole; text chat keeps a fixed shell and scrolls #messagesContainer only */\n #text-chat-panel .widget-container > .voice-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow-y: auto").concat(important, ";\n overflow-x: visible").concat(important, ";\n }\n #text-chat-panel .widget-container > .text-interface {\n flex: 1").concat(important, ";\n min-height: 0").concat(important, ";\n overflow: hidden").concat(important, ";\n overflow-x: visible").concat(important, ";\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\n /* ========================================\n \"About\" info (\"i\") button + dialog\n ======================================== */\n .ttp-header-actions {\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n gap: 4px").concat(important, ";\n }\n .ttp-info-btn {\n background: none").concat(important, ";\n border: none").concat(important, ";\n cursor: pointer").concat(important, ";\n color: currentColor").concat(important, ";\n opacity: 0.7").concat(important, ";\n padding: 4px").concat(important, ";\n margin: 0").concat(important, ";\n display: inline-flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: center").concat(important, ";\n border-radius: 50%").concat(important, ";\n line-height: 0").concat(important, ";\n transition: opacity 0.2s, background 0.2s").concat(important, ";\n flex-shrink: 0").concat(important, ";\n }\n .ttp-info-btn:hover {\n opacity: 1").concat(important, ";\n background: rgba(127,127,127,0.18)").concat(important, ";\n }\n .ttp-info-btn svg { display: block").concat(important, "; }\n /* Floating variant for views without a header row (mobile idle) */\n .ttp-info-btn--floating {\n position: absolute").concat(important, ";\n top: 10px").concat(important, ";\n inset-inline-end: 10px").concat(important, ";\n z-index: 5").concat(important, ";\n }\n .ttp-info-btn--onbadge {\n width: 22px").concat(important, ";\n height: 22px").concat(important, ";\n padding: 3px").concat(important, ";\n }\n .ttp-info-btn--onbadge svg { width: 13px").concat(important, "; height: 13px").concat(important, "; }\n ");
|
|
33465
34046
|
}
|
|
33466
34047
|
}, {
|
|
33467
34048
|
key: "setupWidgetEvents",
|
|
33468
34049
|
value: function setupWidgetEvents() {
|
|
33469
|
-
var
|
|
33470
|
-
_this$config$behavior8
|
|
34050
|
+
var _this9 = this,
|
|
34051
|
+
_this$config$behavior8,
|
|
34052
|
+
_this$config$position5;
|
|
33471
34053
|
if (!this.shadowRoot) return;
|
|
33472
34054
|
|
|
33473
34055
|
// Setup prompt animation visibility and interactions
|
|
@@ -33478,16 +34060,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33478
34060
|
if (launcherBtn) {
|
|
33479
34061
|
launcherBtn.onclick = function (e) {
|
|
33480
34062
|
e.stopPropagation();
|
|
33481
|
-
|
|
33482
|
-
|
|
34063
|
+
// A drag just ended — don't treat the trailing click as "open panel".
|
|
34064
|
+
if (_this9._suppressLauncherClick) return;
|
|
34065
|
+
if (_this9.config.promptAnimation.hideAfterClick) {
|
|
34066
|
+
_this9.hidePrompt();
|
|
33483
34067
|
}
|
|
33484
|
-
|
|
34068
|
+
_this9.togglePanel();
|
|
33485
34069
|
};
|
|
33486
34070
|
}
|
|
33487
34071
|
var closeBtn = this.shadowRoot.getElementById('closeBtn');
|
|
33488
34072
|
if (closeBtn) {
|
|
33489
34073
|
closeBtn.onclick = function () {
|
|
33490
|
-
|
|
34074
|
+
_this9._doTogglePanel();
|
|
33491
34075
|
};
|
|
33492
34076
|
}
|
|
33493
34077
|
|
|
@@ -33495,31 +34079,41 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33495
34079
|
var closeIdle = this.shadowRoot.getElementById('ttpCloseIdle');
|
|
33496
34080
|
if (closeIdle) {
|
|
33497
34081
|
closeIdle.onclick = function () {
|
|
33498
|
-
return
|
|
34082
|
+
return _this9._doTogglePanel();
|
|
33499
34083
|
};
|
|
33500
34084
|
}
|
|
33501
34085
|
var closeActive = this.shadowRoot.getElementById('ttpCloseActive');
|
|
33502
34086
|
if (closeActive) {
|
|
33503
34087
|
closeActive.onclick = function () {
|
|
33504
|
-
return
|
|
34088
|
+
return _this9._doTogglePanel();
|
|
33505
34089
|
};
|
|
33506
34090
|
}
|
|
33507
34091
|
|
|
34092
|
+
// "About" info buttons (present in every view: idle / active / compact /
|
|
34093
|
+
// mobile idle / mobile active / text top-bar). One shared dialog.
|
|
34094
|
+
this.shadowRoot.querySelectorAll('.ttp-info-btn').forEach(function (btn) {
|
|
34095
|
+
btn.onclick = function (e) {
|
|
34096
|
+
e.stopPropagation();
|
|
34097
|
+
e.preventDefault();
|
|
34098
|
+
_this9._openAboutModal();
|
|
34099
|
+
};
|
|
34100
|
+
});
|
|
34101
|
+
|
|
33508
34102
|
// "Send a Message" button in idle view → switch to text interface
|
|
33509
34103
|
var startTextBtn = this.shadowRoot.getElementById('startTextBtn');
|
|
33510
34104
|
if (startTextBtn) {
|
|
33511
34105
|
startTextBtn.onclick = function () {
|
|
33512
|
-
return
|
|
34106
|
+
return _this9.showText();
|
|
33513
34107
|
};
|
|
33514
34108
|
}
|
|
33515
34109
|
var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
|
|
33516
34110
|
if (textUnifiedBackBtn) {
|
|
33517
34111
|
textUnifiedBackBtn.onclick = function () {
|
|
33518
|
-
var
|
|
33519
|
-
var widgetMode = ((
|
|
34112
|
+
var _this9$config$behavio;
|
|
34113
|
+
var widgetMode = ((_this9$config$behavio = _this9.config.behavior) === null || _this9$config$behavio === void 0 ? void 0 : _this9$config$behavio.mode) || 'unified';
|
|
33520
34114
|
if (widgetMode !== 'unified') return;
|
|
33521
|
-
|
|
33522
|
-
|
|
34115
|
+
_this9.showLanding();
|
|
34116
|
+
_this9._openMobileCallTextLanding();
|
|
33523
34117
|
};
|
|
33524
34118
|
}
|
|
33525
34119
|
|
|
@@ -33549,30 +34143,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33549
34143
|
// Setup back button handler
|
|
33550
34144
|
if (backBtn) {
|
|
33551
34145
|
backBtn.onclick = function () {
|
|
33552
|
-
var
|
|
34146
|
+
var _this9$voiceInterface, _this9$voiceInterface3;
|
|
33553
34147
|
// Check if we're showing a domain error — clear it and return to voice hero
|
|
33554
|
-
if ((
|
|
33555
|
-
var
|
|
34148
|
+
if ((_this9$voiceInterface = _this9.voiceInterface) !== null && _this9$voiceInterface !== void 0 && _this9$voiceInterface.isShowingDomainError) {
|
|
34149
|
+
var _this9$voiceInterface2;
|
|
33556
34150
|
console.log('🔙 Back button clicked - clearing domain error and returning to voice hero');
|
|
33557
34151
|
// Clear the domain error flag
|
|
33558
|
-
|
|
34152
|
+
_this9.voiceInterface.isShowingDomainError = false;
|
|
33559
34153
|
// Reset the connecting state (this will restore normal UI)
|
|
33560
|
-
if ((
|
|
33561
|
-
|
|
34154
|
+
if ((_this9$voiceInterface2 = _this9.voiceInterface) !== null && _this9$voiceInterface2 !== void 0 && _this9$voiceInterface2.resetConnectingState) {
|
|
34155
|
+
_this9.voiceInterface.resetConnectingState();
|
|
33562
34156
|
}
|
|
33563
|
-
|
|
33564
|
-
|
|
34157
|
+
_this9.showLanding();
|
|
34158
|
+
_this9._openMobileCallTextLanding();
|
|
33565
34159
|
return;
|
|
33566
34160
|
}
|
|
33567
|
-
if ((
|
|
34161
|
+
if ((_this9$voiceInterface3 = _this9.voiceInterface) !== null && _this9$voiceInterface3 !== void 0 && _this9$voiceInterface3.isActive) {
|
|
33568
34162
|
// If call is active, show message inside widget instead of modal
|
|
33569
|
-
|
|
34163
|
+
_this9.showBackButtonWarning();
|
|
33570
34164
|
} else if (window.innerWidth <= 768) {
|
|
33571
|
-
|
|
33572
|
-
|
|
34165
|
+
_this9.showLanding();
|
|
34166
|
+
_this9._openMobileCallTextLanding();
|
|
33573
34167
|
} else {
|
|
33574
34168
|
// Desktop: return to voice hero (unified home)
|
|
33575
|
-
|
|
34169
|
+
_this9.showLanding();
|
|
33576
34170
|
}
|
|
33577
34171
|
};
|
|
33578
34172
|
}
|
|
@@ -33615,7 +34209,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33615
34209
|
// Setup header button handlers
|
|
33616
34210
|
if (newChatBtn) {
|
|
33617
34211
|
newChatBtn.onclick = function () {
|
|
33618
|
-
return
|
|
34212
|
+
return _this9.textInterface.startNewChat();
|
|
33619
34213
|
};
|
|
33620
34214
|
// Hide new chat on unified home (voice hero) initially
|
|
33621
34215
|
if (isUnified && this.currentView !== 'text') {
|
|
@@ -33626,11 +34220,328 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33626
34220
|
// Mobile floating button & landing overlay
|
|
33627
34221
|
this.setupMobileWidgetEvents();
|
|
33628
34222
|
|
|
34223
|
+
// Optional: make the launcher pill / mobile FAB + the open panel draggable
|
|
34224
|
+
// (they move together as one unit). The minimized strip is wired separately
|
|
34225
|
+
// in _initEcommerceVoiceStrip() since it lives outside the shadow DOM.
|
|
34226
|
+
if ((_this$config$position5 = this.config.position) !== null && _this$config$position5 !== void 0 && _this$config$position5.draggable) {
|
|
34227
|
+
this.setupDraggableWidget();
|
|
34228
|
+
}
|
|
34229
|
+
|
|
33629
34230
|
// Keyboard navigation
|
|
33630
34231
|
if (this.config.accessibility.keyboardNavigation) {
|
|
33631
34232
|
this.setupKeyboardNavigation();
|
|
33632
34233
|
}
|
|
33633
34234
|
}
|
|
34235
|
+
|
|
34236
|
+
/**
|
|
34237
|
+
* Page-scoped namespace for persisted drag positions (origin+path) so the same
|
|
34238
|
+
* widget on different routes keeps independent spots.
|
|
34239
|
+
*/
|
|
34240
|
+
}, {
|
|
34241
|
+
key: "_dragScope",
|
|
34242
|
+
value: function _dragScope() {
|
|
34243
|
+
var scope = '';
|
|
34244
|
+
try {
|
|
34245
|
+
scope = window.location.origin + window.location.pathname;
|
|
34246
|
+
} catch (e) {/* sandboxed */}
|
|
34247
|
+
return scope;
|
|
34248
|
+
}
|
|
34249
|
+
|
|
34250
|
+
/** localStorage key for a dragged surface ('unit' = pill+panel, 'strip'). */
|
|
34251
|
+
}, {
|
|
34252
|
+
key: "_dragStorageKey",
|
|
34253
|
+
value: function _dragStorageKey(kind) {
|
|
34254
|
+
return 'ttp-widget-' + kind + '-pos::' + this._dragScope();
|
|
34255
|
+
}
|
|
34256
|
+
|
|
34257
|
+
/**
|
|
34258
|
+
* The launcher pill and the chat panel move together as one unit. They share a
|
|
34259
|
+
* single translate offset (`this._unitOffset`) so dragging either one (the pill,
|
|
34260
|
+
* the mobile FAB, or a panel header) moves both — they never split apart.
|
|
34261
|
+
*/
|
|
34262
|
+
}, {
|
|
34263
|
+
key: "_unitEls",
|
|
34264
|
+
value: function _unitEls() {
|
|
34265
|
+
var root = this.shadowRoot;
|
|
34266
|
+
if (!root) return [];
|
|
34267
|
+
return [root.getElementById('text-chat-button-container'), root.getElementById('text-chat-panel')].filter(Boolean);
|
|
34268
|
+
}
|
|
34269
|
+
|
|
34270
|
+
/** Apply the shared unit offset as a translate transform to both elements. */
|
|
34271
|
+
}, {
|
|
34272
|
+
key: "_applyUnitOffset",
|
|
34273
|
+
value: function _applyUnitOffset() {
|
|
34274
|
+
var o = this._unitOffset || (this._unitOffset = {
|
|
34275
|
+
x: 0,
|
|
34276
|
+
y: 0
|
|
34277
|
+
});
|
|
34278
|
+
var value = "translate(".concat(o.x, "px, ").concat(o.y, "px)");
|
|
34279
|
+
this._unitEls().forEach(function (el) {
|
|
34280
|
+
return el.style.setProperty('transform', value, 'important');
|
|
34281
|
+
});
|
|
34282
|
+
}
|
|
34283
|
+
|
|
34284
|
+
/**
|
|
34285
|
+
* Base (offset-0) viewport rects of the currently-visible unit elements. The
|
|
34286
|
+
* applied transform equals `this._unitOffset`, so subtracting it recovers the
|
|
34287
|
+
* anchored position. Hidden elements (display:none → 0×0) are skipped.
|
|
34288
|
+
*/
|
|
34289
|
+
}, {
|
|
34290
|
+
key: "_unitBaseRects",
|
|
34291
|
+
value: function _unitBaseRects() {
|
|
34292
|
+
var o = this._unitOffset || {
|
|
34293
|
+
x: 0,
|
|
34294
|
+
y: 0
|
|
34295
|
+
};
|
|
34296
|
+
var rects = [];
|
|
34297
|
+
this._unitEls().forEach(function (el) {
|
|
34298
|
+
var r = el.getBoundingClientRect();
|
|
34299
|
+
if (!r.width && !r.height) return; // hidden
|
|
34300
|
+
rects.push({
|
|
34301
|
+
left: r.left - o.x,
|
|
34302
|
+
top: r.top - o.y,
|
|
34303
|
+
right: r.right - o.x,
|
|
34304
|
+
bottom: r.bottom - o.y
|
|
34305
|
+
});
|
|
34306
|
+
});
|
|
34307
|
+
return rects;
|
|
34308
|
+
}
|
|
34309
|
+
|
|
34310
|
+
/**
|
|
34311
|
+
* Clamp a desired unit offset so every visible unit element stays within the
|
|
34312
|
+
* viewport (8px margin). Constraints from all visible elements are intersected.
|
|
34313
|
+
*/
|
|
34314
|
+
}, {
|
|
34315
|
+
key: "_clampUnitOffset",
|
|
34316
|
+
value: function _clampUnitOffset(x, y, bases) {
|
|
34317
|
+
var margin = 8;
|
|
34318
|
+
var vw = window.innerWidth,
|
|
34319
|
+
vh = window.innerHeight;
|
|
34320
|
+
var minX = -Infinity,
|
|
34321
|
+
maxX = Infinity,
|
|
34322
|
+
minY = -Infinity,
|
|
34323
|
+
maxY = Infinity;
|
|
34324
|
+
bases.forEach(function (b) {
|
|
34325
|
+
minX = Math.max(minX, margin - b.left);
|
|
34326
|
+
maxX = Math.min(maxX, vw - margin - b.right);
|
|
34327
|
+
minY = Math.max(minY, margin - b.top);
|
|
34328
|
+
maxY = Math.min(maxY, vh - margin - b.bottom);
|
|
34329
|
+
});
|
|
34330
|
+
// Element taller/wider than the viewport → keep its top/left edge visible.
|
|
34331
|
+
if (minX > maxX) maxX = minX;
|
|
34332
|
+
if (minY > maxY) maxY = minY;
|
|
34333
|
+
if (!bases.length) return {
|
|
34334
|
+
x: x,
|
|
34335
|
+
y: y
|
|
34336
|
+
};
|
|
34337
|
+
return {
|
|
34338
|
+
x: Math.min(Math.max(x, minX), maxX),
|
|
34339
|
+
y: Math.min(Math.max(y, minY), maxY)
|
|
34340
|
+
};
|
|
34341
|
+
}
|
|
34342
|
+
|
|
34343
|
+
/** Re-clamp the unit to the current viewport (e.g. on resize or panel open). */
|
|
34344
|
+
}, {
|
|
34345
|
+
key: "_reclampUnit",
|
|
34346
|
+
value: function _reclampUnit() {
|
|
34347
|
+
if (!this._unitOffset) return;
|
|
34348
|
+
var bases = this._unitBaseRects();
|
|
34349
|
+
if (!bases.length) return;
|
|
34350
|
+
this._unitOffset = this._clampUnitOffset(this._unitOffset.x, this._unitOffset.y, bases);
|
|
34351
|
+
this._applyUnitOffset();
|
|
34352
|
+
}
|
|
34353
|
+
|
|
34354
|
+
/** Restore a saved unit offset (deferred so elements can be measured at offset 0). */
|
|
34355
|
+
}, {
|
|
34356
|
+
key: "_restoreUnitOffset",
|
|
34357
|
+
value: function _restoreUnitOffset(key) {
|
|
34358
|
+
var _this0 = this;
|
|
34359
|
+
var saved;
|
|
34360
|
+
try {
|
|
34361
|
+
saved = JSON.parse(window.localStorage.getItem(key) || 'null');
|
|
34362
|
+
} catch (e) {
|
|
34363
|
+
return;
|
|
34364
|
+
}
|
|
34365
|
+
if (!saved || typeof saved.x !== 'number' || typeof saved.y !== 'number') return;
|
|
34366
|
+
requestAnimationFrame(function () {
|
|
34367
|
+
_this0._unitOffset = {
|
|
34368
|
+
x: 0,
|
|
34369
|
+
y: 0
|
|
34370
|
+
}; // ensure DOM matches before measuring
|
|
34371
|
+
var bases = _this0._unitBaseRects();
|
|
34372
|
+
_this0._unitOffset = _this0._clampUnitOffset(saved.x, saved.y, bases);
|
|
34373
|
+
_this0._applyUnitOffset();
|
|
34374
|
+
});
|
|
34375
|
+
}
|
|
34376
|
+
|
|
34377
|
+
/**
|
|
34378
|
+
* Wire a single handle to drag the whole pill+panel unit (shared offset).
|
|
34379
|
+
* @param {HTMLElement} handle
|
|
34380
|
+
* @param {Object} opts
|
|
34381
|
+
* @param {boolean} opts.persist
|
|
34382
|
+
* @param {string} opts.key localStorage key
|
|
34383
|
+
* @param {string} [opts.restCursor] idle cursor (default 'grab')
|
|
34384
|
+
* @param {string} [opts.excludeSelector] don't start a drag from these (e.g. buttons)
|
|
34385
|
+
* @param {Function} [opts.onMoved] called once after a real drag ends
|
|
34386
|
+
*/
|
|
34387
|
+
}, {
|
|
34388
|
+
key: "_attachUnitDrag",
|
|
34389
|
+
value: function _attachUnitDrag(handle, opts) {
|
|
34390
|
+
var _this1 = this;
|
|
34391
|
+
var persist = opts.persist,
|
|
34392
|
+
key = opts.key,
|
|
34393
|
+
excludeSelector = opts.excludeSelector,
|
|
34394
|
+
onMoved = opts.onMoved;
|
|
34395
|
+
var restCursor = opts.restCursor || 'grab';
|
|
34396
|
+
handle.style.setProperty('touch-action', 'none');
|
|
34397
|
+
handle.style.setProperty('cursor', restCursor);
|
|
34398
|
+
var DRAG_THRESHOLD = 5; // px before a press becomes a drag
|
|
34399
|
+
var startX = 0,
|
|
34400
|
+
startY = 0,
|
|
34401
|
+
baseX = 0,
|
|
34402
|
+
baseY = 0,
|
|
34403
|
+
bases = [];
|
|
34404
|
+
var dragging = false,
|
|
34405
|
+
moved = false;
|
|
34406
|
+
var onMove = function onMove(e) {
|
|
34407
|
+
var dx = e.clientX - startX;
|
|
34408
|
+
var dy = e.clientY - startY;
|
|
34409
|
+
if (!moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
34410
|
+
moved = true;
|
|
34411
|
+
_this1._unitOffset = _this1._clampUnitOffset(baseX + dx, baseY + dy, bases);
|
|
34412
|
+
_this1._applyUnitOffset();
|
|
34413
|
+
};
|
|
34414
|
+
var _onUp = function onUp(e) {
|
|
34415
|
+
window.removeEventListener('pointermove', onMove);
|
|
34416
|
+
window.removeEventListener('pointerup', _onUp);
|
|
34417
|
+
handle.style.setProperty('cursor', restCursor);
|
|
34418
|
+
try {
|
|
34419
|
+
handle.releasePointerCapture(e.pointerId);
|
|
34420
|
+
} catch (err) {/* not captured */}
|
|
34421
|
+
dragging = false;
|
|
34422
|
+
if (moved) {
|
|
34423
|
+
if (typeof onMoved === 'function') onMoved();
|
|
34424
|
+
if (persist && key) {
|
|
34425
|
+
try {
|
|
34426
|
+
window.localStorage.setItem(key, JSON.stringify(_this1._unitOffset));
|
|
34427
|
+
} catch (err) {/* unavailable */}
|
|
34428
|
+
}
|
|
34429
|
+
}
|
|
34430
|
+
};
|
|
34431
|
+
var onDown = function onDown(e) {
|
|
34432
|
+
if (e.button != null && e.button !== 0) return; // primary / touch / pen only
|
|
34433
|
+
if (dragging) return;
|
|
34434
|
+
if (excludeSelector && e.target && e.target.closest && e.target.closest(excludeSelector)) return;
|
|
34435
|
+
dragging = true;
|
|
34436
|
+
moved = false;
|
|
34437
|
+
var o = _this1._unitOffset || (_this1._unitOffset = {
|
|
34438
|
+
x: 0,
|
|
34439
|
+
y: 0
|
|
34440
|
+
});
|
|
34441
|
+
startX = e.clientX;
|
|
34442
|
+
startY = e.clientY;
|
|
34443
|
+
baseX = o.x;
|
|
34444
|
+
baseY = o.y;
|
|
34445
|
+
bases = _this1._unitBaseRects();
|
|
34446
|
+
handle.style.setProperty('cursor', 'grabbing');
|
|
34447
|
+
try {
|
|
34448
|
+
handle.setPointerCapture(e.pointerId);
|
|
34449
|
+
} catch (err) {/* unsupported */}
|
|
34450
|
+
window.addEventListener('pointermove', onMove);
|
|
34451
|
+
window.addEventListener('pointerup', _onUp);
|
|
34452
|
+
};
|
|
34453
|
+
handle.addEventListener('pointerdown', onDown);
|
|
34454
|
+
}
|
|
34455
|
+
|
|
34456
|
+
/**
|
|
34457
|
+
* Make the launcher pill / mobile FAB AND the open chat panel draggable as one
|
|
34458
|
+
* unit — dragging any of them moves both, so they never split apart. Pill/FAB
|
|
34459
|
+
* drags suppress the trailing click (so the panel doesn't toggle); panel header
|
|
34460
|
+
* bars (.ttp-header / .ttp-call-topbar / .text-interface-top-bar) are drag
|
|
34461
|
+
* handles too, with their interactive controls (e.g. close) excluded.
|
|
34462
|
+
*/
|
|
34463
|
+
}, {
|
|
34464
|
+
key: "setupDraggableWidget",
|
|
34465
|
+
value: function setupDraggableWidget() {
|
|
34466
|
+
var _this$config$position6,
|
|
34467
|
+
_this10 = this;
|
|
34468
|
+
var root = this.shadowRoot;
|
|
34469
|
+
if (!root) return;
|
|
34470
|
+
var container = root.getElementById('text-chat-button-container');
|
|
34471
|
+
var panel = root.getElementById('text-chat-panel');
|
|
34472
|
+
if (!container && !panel) return;
|
|
34473
|
+
this._unitOffset = this._unitOffset || {
|
|
34474
|
+
x: 0,
|
|
34475
|
+
y: 0
|
|
34476
|
+
};
|
|
34477
|
+
var persist = ((_this$config$position6 = this.config.position) === null || _this$config$position6 === void 0 ? void 0 : _this$config$position6.draggablePersist) !== false;
|
|
34478
|
+
var key = this._dragStorageKey('unit');
|
|
34479
|
+
if (persist) this._restoreUnitOffset(key);
|
|
34480
|
+
|
|
34481
|
+
// Launcher handles: pill + mobile FAB (suppress the click after a drag).
|
|
34482
|
+
[root.getElementById('text-chat-button'), root.querySelector('.ttp-mobile-fab')].filter(Boolean).forEach(function (h) {
|
|
34483
|
+
return _this10._attachUnitDrag(h, {
|
|
34484
|
+
persist: persist,
|
|
34485
|
+
key: key,
|
|
34486
|
+
restCursor: 'grab',
|
|
34487
|
+
onMoved: function onMoved() {
|
|
34488
|
+
_this10._suppressLauncherClick = true;
|
|
34489
|
+
setTimeout(function () {
|
|
34490
|
+
_this10._suppressLauncherClick = false;
|
|
34491
|
+
}, 0);
|
|
34492
|
+
}
|
|
34493
|
+
});
|
|
34494
|
+
});
|
|
34495
|
+
|
|
34496
|
+
// Panel handles: header bars across voice idle / active call / text views.
|
|
34497
|
+
if (panel) {
|
|
34498
|
+
['.ttp-header', '.ttp-call-topbar', '.text-interface-top-bar'].map(function (sel) {
|
|
34499
|
+
return panel.querySelector(sel);
|
|
34500
|
+
}).filter(Boolean).forEach(function (h) {
|
|
34501
|
+
return _this10._attachUnitDrag(h, {
|
|
34502
|
+
persist: persist,
|
|
34503
|
+
key: key,
|
|
34504
|
+
restCursor: 'move',
|
|
34505
|
+
excludeSelector: 'button, a, input, textarea, select, [contenteditable]'
|
|
34506
|
+
});
|
|
34507
|
+
});
|
|
34508
|
+
}
|
|
34509
|
+
|
|
34510
|
+
// Re-apply any in-memory offset to freshly-rendered elements (re-render).
|
|
34511
|
+
this._applyUnitOffset();
|
|
34512
|
+
this._bindDragResize();
|
|
34513
|
+
}
|
|
34514
|
+
|
|
34515
|
+
/**
|
|
34516
|
+
* Make the desktop minimized voice strip (EcommerceVoiceStrip) draggable. The
|
|
34517
|
+
* strip lives outside the shadow DOM and owns its own drag logic; we just hand
|
|
34518
|
+
* it a persistence key (so it remembers its spot independently of the unit).
|
|
34519
|
+
*/
|
|
34520
|
+
}, {
|
|
34521
|
+
key: "setupDraggableStrip",
|
|
34522
|
+
value: function setupDraggableStrip() {
|
|
34523
|
+
var _this$config$position7;
|
|
34524
|
+
var strip = this._ecommerceVoiceStrip;
|
|
34525
|
+
if (!strip || typeof strip.enableDrag !== 'function') return;
|
|
34526
|
+
strip.enableDrag({
|
|
34527
|
+
persist: ((_this$config$position7 = this.config.position) === null || _this$config$position7 === void 0 ? void 0 : _this$config$position7.draggablePersist) !== false,
|
|
34528
|
+
storageKey: this._dragStorageKey('strip')
|
|
34529
|
+
});
|
|
34530
|
+
}
|
|
34531
|
+
|
|
34532
|
+
/** Bind a single resize listener that re-clamps every dragged surface. */
|
|
34533
|
+
}, {
|
|
34534
|
+
key: "_bindDragResize",
|
|
34535
|
+
value: function _bindDragResize() {
|
|
34536
|
+
var _this11 = this;
|
|
34537
|
+
if (this._dragResizeBound) return;
|
|
34538
|
+
this._dragResizeBound = true;
|
|
34539
|
+
window.addEventListener('resize', function () {
|
|
34540
|
+
var _this11$_ecommerceVoi, _this11$_ecommerceVoi2;
|
|
34541
|
+
_this11._reclampUnit();
|
|
34542
|
+
(_this11$_ecommerceVoi = _this11._ecommerceVoiceStrip) === null || _this11$_ecommerceVoi === void 0 || (_this11$_ecommerceVoi2 = _this11$_ecommerceVoi.reclampDrag) === null || _this11$_ecommerceVoi2 === void 0 || _this11$_ecommerceVoi2.call(_this11$_ecommerceVoi);
|
|
34543
|
+
});
|
|
34544
|
+
}
|
|
33634
34545
|
}, {
|
|
33635
34546
|
key: "startNewChat",
|
|
33636
34547
|
value: function startNewChat() {
|
|
@@ -33677,9 +34588,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33677
34588
|
}, {
|
|
33678
34589
|
key: "_isDomainErrorVisible",
|
|
33679
34590
|
value: function _isDomainErrorVisible() {
|
|
33680
|
-
var _this$
|
|
33681
|
-
if ((_this$
|
|
33682
|
-
var idleState = (_this$
|
|
34591
|
+
var _this$voiceInterface4, _this$voiceInterface5, _idleState$dataset;
|
|
34592
|
+
if ((_this$voiceInterface4 = this.voiceInterface) !== null && _this$voiceInterface4 !== void 0 && _this$voiceInterface4.isShowingDomainError) return true;
|
|
34593
|
+
var idleState = (_this$voiceInterface5 = this.voiceInterface) === null || _this$voiceInterface5 === void 0 || (_this$voiceInterface5 = _this$voiceInterface5.shadowRoot) === null || _this$voiceInterface5 === void 0 ? void 0 : _this$voiceInterface5.getElementById('voiceIdleState');
|
|
33683
34594
|
return idleState && ((_idleState$dataset = idleState.dataset) === null || _idleState$dataset === void 0 ? void 0 : _idleState$dataset.domainError) === 'true';
|
|
33684
34595
|
}
|
|
33685
34596
|
}, {
|
|
@@ -33707,7 +34618,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33707
34618
|
}, {
|
|
33708
34619
|
key: "_openMobileCallTextLanding",
|
|
33709
34620
|
value: function _openMobileCallTextLanding() {
|
|
33710
|
-
var
|
|
34621
|
+
var _this12 = this;
|
|
33711
34622
|
if (!this.shadowRoot || window.innerWidth > 768) return;
|
|
33712
34623
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33713
34624
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33718,30 +34629,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33718
34629
|
// "Back" button: composedPath includes the panel but not #ttpMobileLanding, so it treated
|
|
33719
34630
|
// the click as "outside" and closed the landing immediately (user only saw the FAB again).
|
|
33720
34631
|
var open = function open() {
|
|
33721
|
-
if (!
|
|
33722
|
-
var panel =
|
|
34632
|
+
if (!_this12.shadowRoot || window.innerWidth > 768) return;
|
|
34633
|
+
var panel = _this12.shadowRoot.getElementById('text-chat-panel');
|
|
33723
34634
|
if (panel) {
|
|
33724
34635
|
panel.classList.remove('open');
|
|
33725
|
-
|
|
34636
|
+
_this12.isOpen = false;
|
|
33726
34637
|
}
|
|
33727
|
-
if (
|
|
33728
|
-
|
|
34638
|
+
if (_this12.config.promptAnimation.hideAfterClick) {
|
|
34639
|
+
_this12.hidePrompt();
|
|
33729
34640
|
}
|
|
33730
|
-
var errorBanner =
|
|
34641
|
+
var errorBanner = _this12.shadowRoot.getElementById('ttpMobileLandingError');
|
|
33731
34642
|
if (errorBanner) errorBanner.style.display = 'none';
|
|
33732
|
-
var fab =
|
|
33733
|
-
var landing =
|
|
34643
|
+
var fab = _this12.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
34644
|
+
var landing = _this12.shadowRoot.getElementById('ttpMobileLanding');
|
|
33734
34645
|
if (!fab || !landing) return;
|
|
33735
34646
|
fab.style.display = 'none';
|
|
33736
34647
|
landing.classList.add('active');
|
|
33737
|
-
|
|
34648
|
+
_this12.isMobileLandingOpen = true;
|
|
33738
34649
|
};
|
|
33739
34650
|
queueMicrotask(open);
|
|
33740
34651
|
}
|
|
33741
34652
|
}, {
|
|
33742
34653
|
key: "setupMobileWidgetEvents",
|
|
33743
34654
|
value: function setupMobileWidgetEvents() {
|
|
33744
|
-
var
|
|
34655
|
+
var _this13 = this;
|
|
33745
34656
|
if (!this.shadowRoot) return;
|
|
33746
34657
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33747
34658
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33749,10 +34660,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33749
34660
|
var closeMobileLanding = function closeMobileLanding() {
|
|
33750
34661
|
mobileLanding.classList.remove('active');
|
|
33751
34662
|
mobileFab.style.display = '';
|
|
33752
|
-
|
|
34663
|
+
_this13.isMobileLandingOpen = false;
|
|
33753
34664
|
};
|
|
33754
34665
|
mobileFab.onclick = function () {
|
|
33755
|
-
|
|
34666
|
+
// A drag just ended — don't open the landing on the trailing click.
|
|
34667
|
+
if (_this13._suppressLauncherClick) return;
|
|
34668
|
+
_this13._openMobileCallTextLanding();
|
|
33756
34669
|
};
|
|
33757
34670
|
var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
|
|
33758
34671
|
if (mobileClose) {
|
|
@@ -33762,18 +34675,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33762
34675
|
if (mobileCallBtn) {
|
|
33763
34676
|
mobileCallBtn.onclick = function () {
|
|
33764
34677
|
closeMobileLanding();
|
|
33765
|
-
var panel =
|
|
34678
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33766
34679
|
if (panel) {
|
|
33767
34680
|
panel.style.removeProperty('display');
|
|
33768
34681
|
panel.classList.add('open');
|
|
33769
|
-
|
|
34682
|
+
_this13.isOpen = true;
|
|
33770
34683
|
}
|
|
33771
34684
|
mobileFab.style.display = 'none';
|
|
33772
|
-
|
|
34685
|
+
_this13.showVoice();
|
|
33773
34686
|
// Landing already chose "Voice call" — start the call (mic permission / pre-prompt) instead of
|
|
33774
34687
|
// leaving users on a second "Start Call" tap that feels broken.
|
|
33775
34688
|
queueMicrotask(function () {
|
|
33776
|
-
|
|
34689
|
+
_this13.startVoiceCall().catch(function (err) {
|
|
33777
34690
|
console.error('[TTPChatWidget] Mobile landing voice start failed:', err);
|
|
33778
34691
|
});
|
|
33779
34692
|
});
|
|
@@ -33783,20 +34696,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33783
34696
|
if (mobileChatBtn) {
|
|
33784
34697
|
mobileChatBtn.onclick = function () {
|
|
33785
34698
|
closeMobileLanding();
|
|
33786
|
-
var panel =
|
|
34699
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33787
34700
|
if (panel) {
|
|
33788
34701
|
panel.style.removeProperty('display');
|
|
33789
34702
|
panel.classList.add('open');
|
|
33790
|
-
|
|
34703
|
+
_this13.isOpen = true;
|
|
33791
34704
|
}
|
|
33792
34705
|
mobileFab.style.display = 'none';
|
|
33793
|
-
|
|
34706
|
+
_this13.showText();
|
|
33794
34707
|
};
|
|
33795
34708
|
}
|
|
33796
34709
|
|
|
33797
34710
|
// Close mobile landing on outside click
|
|
33798
34711
|
document.addEventListener('click', function (e) {
|
|
33799
|
-
if (!
|
|
34712
|
+
if (!_this13.isMobileLandingOpen) return;
|
|
33800
34713
|
var path = e.composedPath();
|
|
33801
34714
|
if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
|
|
33802
34715
|
closeMobileLanding();
|
|
@@ -33805,7 +34718,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33805
34718
|
|
|
33806
34719
|
// Close mobile landing on Escape
|
|
33807
34720
|
document.addEventListener('keydown', function (e) {
|
|
33808
|
-
if (e.key === 'Escape' &&
|
|
34721
|
+
if (e.key === 'Escape' && _this13.isMobileLandingOpen) {
|
|
33809
34722
|
closeMobileLanding();
|
|
33810
34723
|
}
|
|
33811
34724
|
});
|
|
@@ -33821,19 +34734,19 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33821
34734
|
_prevIsMobile = nowMobile;
|
|
33822
34735
|
if (nowMobile) {
|
|
33823
34736
|
// Switched desktop → mobile: close desktop panel so only mobile FAB shows
|
|
33824
|
-
if (
|
|
33825
|
-
var
|
|
33826
|
-
var panel = (
|
|
34737
|
+
if (_this13.isOpen) {
|
|
34738
|
+
var _this13$shadowRoot, _this13$shadowRoot2;
|
|
34739
|
+
var panel = (_this13$shadowRoot = _this13.shadowRoot) === null || _this13$shadowRoot === void 0 ? void 0 : _this13$shadowRoot.getElementById('text-chat-panel');
|
|
33827
34740
|
if (panel) {
|
|
33828
34741
|
panel.classList.remove('open');
|
|
33829
|
-
|
|
34742
|
+
_this13.isOpen = false;
|
|
33830
34743
|
}
|
|
33831
|
-
var pill = (
|
|
34744
|
+
var pill = (_this13$shadowRoot2 = _this13.shadowRoot) === null || _this13$shadowRoot2 === void 0 ? void 0 : _this13$shadowRoot2.getElementById('text-chat-button');
|
|
33832
34745
|
if (pill) pill.classList.remove('open');
|
|
33833
34746
|
}
|
|
33834
34747
|
} else {
|
|
33835
34748
|
// Switched mobile → desktop: close mobile landing/FAB so only desktop pill shows
|
|
33836
|
-
if (
|
|
34749
|
+
if (_this13.isMobileLandingOpen) {
|
|
33837
34750
|
closeMobileLanding();
|
|
33838
34751
|
}
|
|
33839
34752
|
// Ensure mobile FAB is reset to CSS-controlled state (media query hides it on desktop)
|
|
@@ -33845,10 +34758,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33845
34758
|
}, {
|
|
33846
34759
|
key: "setupKeyboardNavigation",
|
|
33847
34760
|
value: function setupKeyboardNavigation() {
|
|
33848
|
-
var
|
|
34761
|
+
var _this14 = this;
|
|
33849
34762
|
document.addEventListener('keydown', function (e) {
|
|
33850
|
-
if (e.key === 'Escape' &&
|
|
33851
|
-
|
|
34763
|
+
if (e.key === 'Escape' && _this14.isOpen) {
|
|
34764
|
+
_this14.togglePanel();
|
|
33852
34765
|
}
|
|
33853
34766
|
});
|
|
33854
34767
|
}
|
|
@@ -33859,7 +34772,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33859
34772
|
}, {
|
|
33860
34773
|
key: "setupPromptAnimation",
|
|
33861
34774
|
value: function setupPromptAnimation() {
|
|
33862
|
-
var
|
|
34775
|
+
var _this15 = this;
|
|
33863
34776
|
if (!this.shadowRoot) return;
|
|
33864
34777
|
var promptConfig = this.config.promptAnimation || {};
|
|
33865
34778
|
// Default to disabled if not specified (enabled === true means explicitly enabled)
|
|
@@ -33889,7 +34802,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33889
34802
|
// Auto-hide after configured seconds (only if widget is closed)
|
|
33890
34803
|
if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
|
|
33891
34804
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
33892
|
-
|
|
34805
|
+
_this15.hidePrompt();
|
|
33893
34806
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
33894
34807
|
}
|
|
33895
34808
|
|
|
@@ -33901,7 +34814,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33901
34814
|
// Wrap the callback to also hide pulse rings
|
|
33902
34815
|
this.config.onConversationStart = function () {
|
|
33903
34816
|
// Hide pulse rings when call starts
|
|
33904
|
-
var pulseRings =
|
|
34817
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33905
34818
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33906
34819
|
|
|
33907
34820
|
// Call original callback if it exists
|
|
@@ -33913,7 +34826,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33913
34826
|
// Also listen to recordingStarted event from SDK if available
|
|
33914
34827
|
if (this.voiceInterface.sdk.voiceSDK) {
|
|
33915
34828
|
this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
|
|
33916
|
-
var pulseRings =
|
|
34829
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33917
34830
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33918
34831
|
});
|
|
33919
34832
|
}
|
|
@@ -33961,7 +34874,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33961
34874
|
}, {
|
|
33962
34875
|
key: "showPrompt",
|
|
33963
34876
|
value: function showPrompt() {
|
|
33964
|
-
var
|
|
34877
|
+
var _this16 = this;
|
|
33965
34878
|
if (!this.shadowRoot) return;
|
|
33966
34879
|
var promptConfig = this.config.promptAnimation || {};
|
|
33967
34880
|
// Default to enabled if not specified
|
|
@@ -33981,8 +34894,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33981
34894
|
// Function to actually show the elements
|
|
33982
34895
|
var doShow = function doShow() {
|
|
33983
34896
|
// Show prompt bubble (check both shadow root and document for compatibility)
|
|
33984
|
-
var promptBubble =
|
|
33985
|
-
if (!promptBubble &&
|
|
34897
|
+
var promptBubble = _this16.shadowRoot.getElementById('prompt-bubble');
|
|
34898
|
+
if (!promptBubble && _this16.shadowRoot !== document) {
|
|
33986
34899
|
promptBubble = document.getElementById('prompt-bubble');
|
|
33987
34900
|
}
|
|
33988
34901
|
if (promptBubble) {
|
|
@@ -33996,8 +34909,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33996
34909
|
|
|
33997
34910
|
// Show pulse rings if enabled
|
|
33998
34911
|
if (promptConfig.showPulseRings !== false) {
|
|
33999
|
-
var _pulseRings =
|
|
34000
|
-
if (!_pulseRings &&
|
|
34912
|
+
var _pulseRings = _this16.shadowRoot.getElementById('prompt-pulse-rings');
|
|
34913
|
+
if (!_pulseRings && _this16.shadowRoot !== document) {
|
|
34001
34914
|
_pulseRings = document.getElementById('prompt-pulse-rings');
|
|
34002
34915
|
}
|
|
34003
34916
|
if (_pulseRings) {
|
|
@@ -34034,7 +34947,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34034
34947
|
}
|
|
34035
34948
|
// Start new timer
|
|
34036
34949
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
34037
|
-
|
|
34950
|
+
_this16.hidePrompt();
|
|
34038
34951
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
34039
34952
|
}
|
|
34040
34953
|
}
|
|
@@ -34050,14 +34963,23 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34050
34963
|
}, {
|
|
34051
34964
|
key: "_doTogglePanel",
|
|
34052
34965
|
value: function _doTogglePanel() {
|
|
34053
|
-
var
|
|
34966
|
+
var _this17 = this;
|
|
34054
34967
|
if (!this.shadowRoot) return;
|
|
34055
34968
|
this.isOpen = !this.isOpen;
|
|
34056
34969
|
var panel = this.shadowRoot.getElementById('text-chat-panel');
|
|
34057
34970
|
if (panel) {
|
|
34058
34971
|
panel.classList.toggle('open');
|
|
34059
34972
|
if (this.isOpen) {
|
|
34973
|
+
var _this$config$position8;
|
|
34060
34974
|
panel.style.removeProperty('display');
|
|
34975
|
+
// The panel joins the dragged unit when it opens; re-clamp now that it
|
|
34976
|
+
// has real dimensions (it was hidden/zero-size while closed).
|
|
34977
|
+
if ((_this$config$position8 = this.config.position) !== null && _this$config$position8 !== void 0 && _this$config$position8.draggable) {
|
|
34978
|
+
this._applyUnitOffset();
|
|
34979
|
+
requestAnimationFrame(function () {
|
|
34980
|
+
return _this17._reclampUnit();
|
|
34981
|
+
});
|
|
34982
|
+
}
|
|
34061
34983
|
}
|
|
34062
34984
|
}
|
|
34063
34985
|
|
|
@@ -34072,7 +34994,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34072
34994
|
// Panel is opening - hide prompt
|
|
34073
34995
|
this.hidePrompt();
|
|
34074
34996
|
setTimeout(function () {
|
|
34075
|
-
var input =
|
|
34997
|
+
var input = _this17.shadowRoot.getElementById('messageInput');
|
|
34076
34998
|
if (input) input.focus();
|
|
34077
34999
|
}, 100);
|
|
34078
35000
|
} else {
|
|
@@ -34084,13 +35006,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34084
35006
|
// Panel is closing - show prompt (if enabled)
|
|
34085
35007
|
this.showPrompt();
|
|
34086
35008
|
setTimeout(function () {
|
|
34087
|
-
var
|
|
34088
|
-
var promptBubble =
|
|
35009
|
+
var _this17$config$prompt;
|
|
35010
|
+
var promptBubble = _this17.shadowRoot.getElementById('prompt-bubble');
|
|
34089
35011
|
if (promptBubble && promptBubble.style.display === 'none') {
|
|
34090
35012
|
promptBubble.style.display = 'block';
|
|
34091
35013
|
}
|
|
34092
|
-
var pulseRings =
|
|
34093
|
-
if (pulseRings && ((
|
|
35014
|
+
var pulseRings = _this17.shadowRoot.getElementById('prompt-pulse-rings');
|
|
35015
|
+
if (pulseRings && ((_this17$config$prompt = _this17.config.promptAnimation) === null || _this17$config$prompt === void 0 ? void 0 : _this17$config$prompt.showPulseRings) !== false) {
|
|
34094
35016
|
if (pulseRings.style.display === 'none') {
|
|
34095
35017
|
pulseRings.style.display = 'block';
|
|
34096
35018
|
}
|
|
@@ -34282,8 +35204,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34282
35204
|
}, {
|
|
34283
35205
|
key: "showBackButtonWarning",
|
|
34284
35206
|
value: function showBackButtonWarning() {
|
|
34285
|
-
var _this$
|
|
34286
|
-
if (!((_this$
|
|
35207
|
+
var _this$voiceInterface6, _this$voiceInterface$;
|
|
35208
|
+
if (!((_this$voiceInterface6 = this.voiceInterface) !== null && _this$voiceInterface6 !== void 0 && _this$voiceInterface6.isActive)) return;
|
|
34287
35209
|
|
|
34288
35210
|
// Show warning message in the voice interface
|
|
34289
35211
|
if ((_this$voiceInterface$ = this.voiceInterface.desktop) !== null && _this$voiceInterface$ !== void 0 && _this$voiceInterface$.showBackButtonWarning) {
|
|
@@ -34364,7 +35286,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34364
35286
|
_this$config$voice0,
|
|
34365
35287
|
_this$config$voice1,
|
|
34366
35288
|
_this$config$voice10,
|
|
34367
|
-
|
|
35289
|
+
_this18 = this;
|
|
34368
35290
|
// Deep merge nested objects
|
|
34369
35291
|
var mergedConfig = _objectSpread({}, this.config);
|
|
34370
35292
|
|
|
@@ -34582,20 +35504,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34582
35504
|
outputBitDepth: ((_this$config$voice10 = this.config.voice) === null || _this$config$voice10 === void 0 ? void 0 : _this$config$voice10.outputBitDepth) || 16,
|
|
34583
35505
|
desktopMinimizedEcommerceStripUi: desktopMinimizedEcommerceStripUi,
|
|
34584
35506
|
onDesktopMinimizedStripCallStart: desktopMinimizedEcommerceStripUi ? function () {
|
|
34585
|
-
var
|
|
34586
|
-
(
|
|
34587
|
-
if (
|
|
34588
|
-
|
|
34589
|
-
|
|
35507
|
+
var _this18$_ecommerceVoi;
|
|
35508
|
+
(_this18$_ecommerceVoi = _this18._ecommerceVoiceStrip) === null || _this18$_ecommerceVoi === void 0 || _this18$_ecommerceVoi.show();
|
|
35509
|
+
if (_this18.isOpen) _this18.minimize();
|
|
35510
|
+
_this18._setPanelFooterVisible(false);
|
|
35511
|
+
_this18._setEcommerceStripLauncherVisible(false);
|
|
34590
35512
|
} : undefined,
|
|
34591
35513
|
onDesktopMinimizedStripLauncherRestore: desktopMinimizedEcommerceStripUi ? function () {
|
|
34592
|
-
return
|
|
35514
|
+
return _this18._restoreDesktopEcommerceStripChrome();
|
|
34593
35515
|
} : undefined,
|
|
34594
35516
|
// Pass event callbacks to voice interface (forward only; panel is not auto-minimized on call start)
|
|
34595
35517
|
onConversationStart: function onConversationStart() {
|
|
34596
|
-
if (typeof
|
|
34597
|
-
var
|
|
34598
|
-
(
|
|
35518
|
+
if (typeof _this18.config.onConversationStart === 'function') {
|
|
35519
|
+
var _this18$config;
|
|
35520
|
+
(_this18$config = _this18.config).onConversationStart.apply(_this18$config, arguments);
|
|
34599
35521
|
}
|
|
34600
35522
|
},
|
|
34601
35523
|
onConversationEnd: this.config.onConversationEnd,
|
|
@@ -34604,48 +35526,48 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34604
35526
|
onAudioStoppedPlaying: this.config.onAudioStoppedPlaying,
|
|
34605
35527
|
onSubtitleDisplay: this.config.onSubtitleDisplay,
|
|
34606
35528
|
onCallEnd: function onCallEnd() {
|
|
34607
|
-
var
|
|
34608
|
-
if (
|
|
34609
|
-
var widgetMode = ((
|
|
35529
|
+
var _this18$config$behavi;
|
|
35530
|
+
if (_this18._isDomainErrorVisible()) return;
|
|
35531
|
+
var widgetMode = ((_this18$config$behavi = _this18.config.behavior) === null || _this18$config$behavi === void 0 ? void 0 : _this18$config$behavi.mode) || 'unified';
|
|
34610
35532
|
if (widgetMode === 'unified') {
|
|
34611
35533
|
if (window.innerWidth <= 768) {
|
|
34612
|
-
var
|
|
34613
|
-
var panel = (
|
|
35534
|
+
var _this18$shadowRoot, _this18$shadowRoot2;
|
|
35535
|
+
var panel = (_this18$shadowRoot = _this18.shadowRoot) === null || _this18$shadowRoot === void 0 ? void 0 : _this18$shadowRoot.getElementById('text-chat-panel');
|
|
34614
35536
|
if (panel) {
|
|
34615
35537
|
panel.classList.remove('open');
|
|
34616
|
-
|
|
35538
|
+
_this18.isOpen = false;
|
|
34617
35539
|
}
|
|
34618
|
-
var fab = (
|
|
35540
|
+
var fab = (_this18$shadowRoot2 = _this18.shadowRoot) === null || _this18$shadowRoot2 === void 0 ? void 0 : _this18$shadowRoot2.querySelector('.ttp-mobile-fab');
|
|
34619
35541
|
if (fab) fab.style.display = '';
|
|
34620
35542
|
}
|
|
34621
|
-
|
|
35543
|
+
_this18.showLanding();
|
|
34622
35544
|
}
|
|
34623
35545
|
},
|
|
34624
35546
|
onShowVoice: function onShowVoice() {
|
|
34625
|
-
|
|
35547
|
+
_this18.showVoice();
|
|
34626
35548
|
},
|
|
34627
35549
|
onShowLanding: function onShowLanding() {
|
|
34628
|
-
|
|
35550
|
+
_this18.showLanding();
|
|
34629
35551
|
},
|
|
34630
35552
|
onDisclaimerDeclined: function onDisclaimerDeclined() {
|
|
34631
|
-
var
|
|
34632
|
-
if (
|
|
34633
|
-
var widgetMode = ((
|
|
35553
|
+
var _this18$config$behavi2;
|
|
35554
|
+
if (_this18._isDomainErrorVisible()) return;
|
|
35555
|
+
var widgetMode = ((_this18$config$behavi2 = _this18.config.behavior) === null || _this18$config$behavi2 === void 0 ? void 0 : _this18$config$behavi2.mode) || 'unified';
|
|
34634
35556
|
if (widgetMode === 'voice-only') {
|
|
34635
|
-
|
|
35557
|
+
_this18.showVoice();
|
|
34636
35558
|
return;
|
|
34637
35559
|
}
|
|
34638
35560
|
if (widgetMode !== 'unified') return;
|
|
34639
35561
|
if (window.innerWidth <= 768) {
|
|
34640
|
-
var
|
|
34641
|
-
var panel = (
|
|
35562
|
+
var _this18$shadowRoot3;
|
|
35563
|
+
var panel = (_this18$shadowRoot3 = _this18.shadowRoot) === null || _this18$shadowRoot3 === void 0 ? void 0 : _this18$shadowRoot3.getElementById('text-chat-panel');
|
|
34642
35564
|
if (panel) {
|
|
34643
35565
|
panel.classList.remove('open');
|
|
34644
|
-
|
|
35566
|
+
_this18.isOpen = false;
|
|
34645
35567
|
}
|
|
34646
|
-
|
|
35568
|
+
_this18._openMobileCallTextLanding();
|
|
34647
35569
|
} else {
|
|
34648
|
-
|
|
35570
|
+
_this18.showLanding();
|
|
34649
35571
|
}
|
|
34650
35572
|
},
|
|
34651
35573
|
direction: this.getEffectiveTextDirection()
|
|
@@ -34692,8 +35614,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34692
35614
|
}, {
|
|
34693
35615
|
key: "_initEcommerceVoiceStrip",
|
|
34694
35616
|
value: function _initEcommerceVoiceStrip() {
|
|
34695
|
-
var
|
|
34696
|
-
_this$
|
|
35617
|
+
var _this19 = this,
|
|
35618
|
+
_this$config$position9,
|
|
35619
|
+
_this$voiceInterface7;
|
|
34697
35620
|
var flavor = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
34698
35621
|
if (window.innerWidth <= 768) return;
|
|
34699
35622
|
if (!flavor || flavor.callView !== 'minimized') return;
|
|
@@ -34714,31 +35637,34 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34714
35637
|
endCallButtonColor: v.endCallButtonColor || '#ef4444'
|
|
34715
35638
|
},
|
|
34716
35639
|
getVoiceUiState: function getVoiceUiState() {
|
|
34717
|
-
var
|
|
35640
|
+
var _this19$voiceInterfac, _this19$voiceInterfac2, _this19$voiceInterfac3;
|
|
34718
35641
|
return {
|
|
34719
|
-
isMicMuted: !!((
|
|
34720
|
-
isPaused: !!((
|
|
34721
|
-
isSpeakerMuted: !!((
|
|
35642
|
+
isMicMuted: !!((_this19$voiceInterfac = _this19.voiceInterface) !== null && _this19$voiceInterfac !== void 0 && _this19$voiceInterfac.isMicMuted),
|
|
35643
|
+
isPaused: !!((_this19$voiceInterfac2 = _this19.voiceInterface) !== null && _this19$voiceInterfac2 !== void 0 && _this19$voiceInterfac2.isPaused),
|
|
35644
|
+
isSpeakerMuted: !!((_this19$voiceInterfac3 = _this19.voiceInterface) !== null && _this19$voiceInterfac3 !== void 0 && _this19$voiceInterfac3.isSpeakerMuted)
|
|
34722
35645
|
};
|
|
34723
35646
|
},
|
|
35647
|
+
onAbout: function onAbout() {
|
|
35648
|
+
return _this19._openAboutModal();
|
|
35649
|
+
},
|
|
34724
35650
|
onHangup: function onHangup() {
|
|
34725
|
-
if (
|
|
35651
|
+
if (_this19.voiceInterface) _this19.voiceInterface.endVoiceCall();
|
|
34726
35652
|
},
|
|
34727
35653
|
onToggleMute: function onToggleMute() {
|
|
34728
|
-
if (
|
|
35654
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleMute();
|
|
34729
35655
|
strip.syncFromVoice();
|
|
34730
35656
|
},
|
|
34731
35657
|
onTogglePause: function onTogglePause() {
|
|
34732
|
-
if (
|
|
35658
|
+
if (_this19.voiceInterface) _this19.voiceInterface.togglePause();
|
|
34733
35659
|
strip.syncFromVoice();
|
|
34734
35660
|
},
|
|
34735
35661
|
onToggleSpeaker: function onToggleSpeaker() {
|
|
34736
|
-
if (
|
|
35662
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleSpeaker();
|
|
34737
35663
|
strip.syncFromVoice();
|
|
34738
35664
|
},
|
|
34739
35665
|
onSendText: function onSendText(text) {
|
|
34740
|
-
var
|
|
34741
|
-
var voiceSDK = (
|
|
35666
|
+
var _this19$voiceInterfac4;
|
|
35667
|
+
var voiceSDK = (_this19$voiceInterfac4 = _this19.voiceInterface) === null || _this19$voiceInterfac4 === void 0 || (_this19$voiceInterfac4 = _this19$voiceInterfac4.sdk) === null || _this19$voiceInterfac4 === void 0 ? void 0 : _this19$voiceInterfac4.voiceSDK;
|
|
34742
35668
|
if (voiceSDK && typeof voiceSDK.sendMessage === 'function') {
|
|
34743
35669
|
voiceSDK.sendMessage({
|
|
34744
35670
|
t: 'text_inject',
|
|
@@ -34749,8 +35675,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34749
35675
|
});
|
|
34750
35676
|
this._ecommerceVoiceStrip = strip;
|
|
34751
35677
|
|
|
35678
|
+
// Make the strip draggable too when position.draggable is enabled.
|
|
35679
|
+
if ((_this$config$position9 = this.config.position) !== null && _this$config$position9 !== void 0 && _this$config$position9.draggable) {
|
|
35680
|
+
this.setupDraggableStrip();
|
|
35681
|
+
}
|
|
35682
|
+
|
|
34752
35683
|
// Show strip when conversation starts
|
|
34753
|
-
var agentSDK = (_this$
|
|
35684
|
+
var agentSDK = (_this$voiceInterface7 = this.voiceInterface) === null || _this$voiceInterface7 === void 0 ? void 0 : _this$voiceInterface7.sdk;
|
|
34754
35685
|
if (agentSDK) {
|
|
34755
35686
|
var origConvStart = agentSDK.onConversationStart;
|
|
34756
35687
|
agentSDK.onConversationStart = function () {
|
|
@@ -34788,7 +35719,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34788
35719
|
var _this$voiceInterface$2;
|
|
34789
35720
|
var origOnCallEnd = this.voiceInterface.config.onCallEnd;
|
|
34790
35721
|
this.voiceInterface.config.onCallEnd = function () {
|
|
34791
|
-
|
|
35722
|
+
_this19._restoreDesktopEcommerceStripChrome();
|
|
34792
35723
|
if (typeof origOnCallEnd === 'function') origOnCallEnd();
|
|
34793
35724
|
};
|
|
34794
35725
|
|
|
@@ -34912,7 +35843,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34912
35843
|
key: "injectData",
|
|
34913
35844
|
value: (function () {
|
|
34914
35845
|
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
34915
|
-
var _this$
|
|
35846
|
+
var _this$voiceInterface8;
|
|
34916
35847
|
var options,
|
|
34917
35848
|
voiceSDK,
|
|
34918
35849
|
ack,
|
|
@@ -34937,7 +35868,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34937
35868
|
throw new Error('Voice call is not active');
|
|
34938
35869
|
case 2:
|
|
34939
35870
|
// Check if SDK is available
|
|
34940
|
-
voiceSDK = (_this$
|
|
35871
|
+
voiceSDK = (_this$voiceInterface8 = this.voiceInterface) === null || _this$voiceInterface8 === void 0 ? void 0 : _this$voiceInterface8.getVoiceSDK();
|
|
34941
35872
|
if (voiceSDK) {
|
|
34942
35873
|
_context6.n = 3;
|
|
34943
35874
|
break;
|
|
@@ -35202,7 +36133,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35202
36133
|
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...';
|
|
35203
36134
|
var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
|
|
35204
36135
|
var backArrow = this.config.direction === 'rtl' ? '→' : '←';
|
|
35205
|
-
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>") : '';
|
|
36136
|
+
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 <button type=\"button\" class=\"ttp-info-btn\" aria-label=\"").concat(this.t('aboutTitle') || 'About', "\" title=\"").concat(this.t('aboutTitle') || 'About', "\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\n <line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"16\"/>\n <circle cx=\"12\" cy=\"7.7\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>\n </div>") : '';
|
|
35206
36137
|
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) || '14px', "; 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>");
|
|
35207
36138
|
}
|
|
35208
36139
|
|
|
@@ -35334,7 +36265,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35334
36265
|
|
|
35335
36266
|
// Add !important to display rules when not using Shadow DOM (to override theme CSS)
|
|
35336
36267
|
var important = this.config.useShadowDOM === false ? ' !important' : '';
|
|
35337
|
-
return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 10px 12px 8px").concat(important, ";\n border-bottom: 1px solid ").concat(topBarBorder).concat(important, ";\n background: ").concat(topBarBg).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: ").concat(backBtnColor).concat(important, ";\n font-size: 16px").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: ").concat(backBtnHoverBg).concat(important, ";\n color: ").concat(backBtnHoverColor).concat(important, ";\n }\n .text-interface-back-icon {\n font-size: 18px").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: ").concat(messagesAreaBg).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: ").concat(emptyMuted).concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 52px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 22px").concat(important, "; font-weight: 700").concat(important, "; color: ").concat(emptyTitle).concat(important, "; }\n .empty-state-text { font-size: 15px").concat(important, "; max-width: 300px").concat(important, "; line-height: 1.45").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: 14px 16px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize).concat(important, "; \n line-height: 1.45").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 }\n .message.user .message-bubble { \n background: ").concat(userBubbleBg).concat(important, "; \n color: ").concat(userBubbleTextColor).concat(important, "; \n }\n .message.agent .message-bubble { \n background: ").concat(agentBubbleBg).concat(important, "; \n color: ").concat(agentBubbleTextColor).concat(important, "; \n border: ").concat(agentBubbleBorder).concat(important, "; \n }\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: ").concat(avatarSize).concat(important, "; \n height: ").concat(avatarSize).concat(important, "; \n min-width: ").concat(avatarSize).concat(important, "; \n border-radius: 50%").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: ").concat(useVoiceTheme ? '14' : '20', "px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n box-sizing: border-box").concat(important, "; \n }\n .message-avatar.user { background: ").concat(avatarUserBg).concat(important, "; color: ").concat(avatarUserColor).concat(important, "; }\n .message-avatar.agent { background: ").concat(avatarAgentBg).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: ").concat(inputContainerBg).concat(important, ";\n border-top: 1px solid ").concat(inputContainerBorderTop).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: ").concat(TEXT_INPUT_MIN_HEIGHT_PX, "px").concat(important, ";\n max-height: ").concat(TEXT_INPUT_MAX_HEIGHT_PX, "px").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.4").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(inputFocusBg).concat(important, ";\n box-shadow: ").concat(inputFocusBoxShadow, ";\n }\n \n .message-input::placeholder {\n color: ").concat(placeholderColor).concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 44px").concat(important, ";\n height: 44px").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) || '20px', ";\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(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.32)").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(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.42)").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: rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", ").concat(typingDotAlpha, ")").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(errorBubbleBg, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: ").concat(errorBubbleColor).concat(important, ";\n border: ").concat(errorBubbleBorder).concat(important, ";\n font-size: ").concat(messages.fontSize).concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n \n ").concat(useVoiceTheme ? "\n #textInterface.active .input-container .send-button-hint {\n color: rgba(255,255,255,0.72)".concat(important, ";\n }\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: ").concat(messages.fontSize).concat(important, ";\n padding: 12px 14px").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: 44px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 20px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 14px").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: ").concat(messages.fontSize).concat(important, ";\n padding: 10px 12px").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 ");
|
|
36268
|
+
return "\n .text-interface-top-bar {\n flex-shrink: 0".concat(important, ";\n padding: 10px 12px 8px").concat(important, ";\n border-bottom: 1px solid ").concat(topBarBorder).concat(important, ";\n background: ").concat(topBarBg).concat(important, ";\n display: flex").concat(important, ";\n align-items: center").concat(important, ";\n justify-content: space-between").concat(important, ";\n }\n .text-interface-top-bar .ttp-info-btn {\n color: ").concat(backBtnColor).concat(important, ";\n }\n .text-interface-top-bar .ttp-info-btn:hover {\n background: ").concat(backBtnHoverBg).concat(important, ";\n color: ").concat(backBtnHoverColor).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: ").concat(backBtnColor).concat(important, ";\n font-size: 16px").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: ").concat(backBtnHoverBg).concat(important, ";\n color: ").concat(backBtnHoverColor).concat(important, ";\n }\n .text-interface-back-icon {\n font-size: 18px").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: ").concat(messagesAreaBg).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: ").concat(emptyMuted).concat(important, "; \n text-align: center").concat(important, "; \n padding: 20px").concat(important, "; \n }\n .empty-state-icon { font-size: 52px").concat(important, "; opacity: 0.3").concat(important, "; }\n .empty-state-title { font-size: 22px").concat(important, "; font-weight: 700").concat(important, "; color: ").concat(emptyTitle).concat(important, "; }\n .empty-state-text { font-size: 15px").concat(important, "; max-width: 300px").concat(important, "; line-height: 1.45").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: 14px 16px").concat(important, "; \n border-radius: ").concat(messages.borderRadius, "px").concat(important, "; \n max-width: 80%").concat(important, "; \n font-size: ").concat(messages.fontSize).concat(important, "; \n line-height: 1.45").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 }\n .message.user .message-bubble { \n background: ").concat(userBubbleBg).concat(important, "; \n color: ").concat(userBubbleTextColor).concat(important, "; \n }\n .message.agent .message-bubble { \n background: ").concat(agentBubbleBg).concat(important, "; \n color: ").concat(agentBubbleTextColor).concat(important, "; \n border: ").concat(agentBubbleBorder).concat(important, "; \n }\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: ").concat(avatarSize).concat(important, "; \n height: ").concat(avatarSize).concat(important, "; \n min-width: ").concat(avatarSize).concat(important, "; \n border-radius: 50%").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: ").concat(useVoiceTheme ? '14' : '20', "px").concat(important, "; \n line-height: 1").concat(important, "; \n background: transparent").concat(important, "; \n border: none").concat(important, "; \n box-sizing: border-box").concat(important, "; \n }\n .message-avatar.user { background: ").concat(avatarUserBg).concat(important, "; color: ").concat(avatarUserColor).concat(important, "; }\n .message-avatar.agent { background: ").concat(avatarAgentBg).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: ").concat(inputContainerBg).concat(important, ";\n border-top: 1px solid ").concat(inputContainerBorderTop).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: ").concat(TEXT_INPUT_MIN_HEIGHT_PX, "px").concat(important, ";\n max-height: ").concat(TEXT_INPUT_MAX_HEIGHT_PX, "px").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.4").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(inputFocusBg).concat(important, ";\n box-shadow: ").concat(inputFocusBoxShadow, ";\n }\n \n .message-input::placeholder {\n color: ").concat(placeholderColor).concat(important, ";\n text-align: ").concat(this.config.direction === 'rtl' ? 'right' : 'left').concat(important, ";\n }\n \n .send-button {\n width: 44px").concat(important, ";\n height: 44px").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) || '20px', ";\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(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.32)").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(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", 0.42)").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: rgba(").concat(accentRgb[0], ", ").concat(accentRgb[1], ", ").concat(accentRgb[2], ", ").concat(typingDotAlpha, ")").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(errorBubbleBg, ";\n border-radius: ").concat(messages.borderRadius, "px;\n color: ").concat(errorBubbleColor).concat(important, ";\n border: ").concat(errorBubbleBorder).concat(important, ";\n font-size: ").concat(messages.fontSize).concat(important, ";\n margin: 8px 0").concat(important, ";\n }\n \n ").concat(useVoiceTheme ? "\n #textInterface.active .input-container .send-button-hint {\n color: rgba(255,255,255,0.72)".concat(important, ";\n }\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: ").concat(messages.fontSize).concat(important, ";\n padding: 12px 14px").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: 44px").concat(important, ";\n }\n \n .empty-state-title {\n font-size: 20px").concat(important, ";\n }\n \n .empty-state-text {\n font-size: 14px").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: ").concat(messages.fontSize).concat(important, ";\n padding: 10px 12px").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 ");
|
|
35338
36269
|
}
|
|
35339
36270
|
|
|
35340
36271
|
/**
|
|
@@ -37412,6 +38343,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37412
38343
|
clearInterval(this.callTimerInterval);
|
|
37413
38344
|
this.callTimerInterval = null;
|
|
37414
38345
|
}
|
|
38346
|
+
this.callStartTime = null;
|
|
37415
38347
|
|
|
37416
38348
|
// Hide active state, show idle state first
|
|
37417
38349
|
activeState = this.shadowRoot.getElementById('voiceActiveState');
|
|
@@ -37580,6 +38512,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37580
38512
|
clearInterval(this.callTimerInterval);
|
|
37581
38513
|
this.callTimerInterval = null;
|
|
37582
38514
|
}
|
|
38515
|
+
// Reset the start time so the next call's timer block (gated on !callStartTime)
|
|
38516
|
+
// actually restarts the interval. Without this, the timer only ever runs for the
|
|
38517
|
+
// first call and stays stuck at 00:00 on every subsequent call.
|
|
38518
|
+
this.callStartTime = null;
|
|
37583
38519
|
|
|
37584
38520
|
// Clean up text inject timeouts and handlers (desktop)
|
|
37585
38521
|
if (this._textInjectTimeout) {
|
|
@@ -40327,6 +41263,21 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40327
41263
|
return this.voiceInterface.getTooltip(key);
|
|
40328
41264
|
}
|
|
40329
41265
|
|
|
41266
|
+
/**
|
|
41267
|
+
* Shared "About" info ("i") button markup. Opens the About dialog
|
|
41268
|
+
* (SDK version + last conversation id) wired by TTPChatWidget.
|
|
41269
|
+
* @param {string} [extraClass] - extra class(es) for positioning per view
|
|
41270
|
+
* @returns {string}
|
|
41271
|
+
*/
|
|
41272
|
+
}, {
|
|
41273
|
+
key: "infoButton",
|
|
41274
|
+
value: function infoButton() {
|
|
41275
|
+
var extraClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
41276
|
+
var cls = extraClass ? "ttp-info-btn ".concat(extraClass) : 'ttp-info-btn';
|
|
41277
|
+
var label = this.t('aboutTitle') || 'About';
|
|
41278
|
+
return "<button type=\"button\" class=\"".concat(cls, "\" aria-label=\"").concat(escapeHtmlAttr(label), "\" title=\"").concat(escapeHtmlAttr(label), "\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"9\"/>\n <line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"16\"/>\n <circle cx=\"12\" cy=\"7.7\" r=\"1.05\" fill=\"currentColor\" stroke=\"none\"/>\n </svg>\n </button>");
|
|
41279
|
+
}
|
|
41280
|
+
|
|
40330
41281
|
/**
|
|
40331
41282
|
* Generate HTML for voice interface.
|
|
40332
41283
|
* Automatically detects mobile vs desktop based on voiceInterface.isMobile
|
|
@@ -40357,7 +41308,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40357
41308
|
var transcriptPlaceholder = this.t('transcriptWillAppear') || '';
|
|
40358
41309
|
var transcriptDir = (0,_rtlText_js__WEBPACK_IMPORTED_MODULE_0__.dirForTranscriptSnippet)(transcriptPlaceholder, this.config);
|
|
40359
41310
|
var voiceInputDir = (0,_rtlText_js__WEBPACK_IMPORTED_MODULE_0__.dirForAssistantStreamingText)(this.config);
|
|
40360
|
-
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 ").concat((((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) || 'unified') !== 'voice-only' ? "\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 ") : '', "\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-ctrl-btn\" id=\"desktopPauseBtn\" title=\"Pause call\" aria-label=\"Pause call\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" class=\"desktop-pause-icon\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" class=\"desktop-play-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"6,4 20,12 6,20\"/>\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 <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 </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 secondary\" id=\"desktopPauseBtnCompact\" title=\"Pause call\" aria-label=\"Pause call\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" class=\"desktop-pause-icon\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" class=\"desktop-play-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"6,4 20,12 6,20\"/>\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 <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 </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\" dir=\"").concat(transcriptDir, "\">\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(transcriptDir, "\">\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(voiceInputDir, "\" 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>");
|
|
41311
|
+
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 <div class=\"ttp-header-actions\">\n ").concat(this.infoButton(), "\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>\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 ").concat((((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) || 'unified') !== 'voice-only' ? "\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 ") : '', "\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 <div class=\"ttp-header-actions\">\n ").concat(this.infoButton(), "\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 </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-ctrl-btn\" id=\"desktopPauseBtn\" title=\"Pause call\" aria-label=\"Pause call\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" class=\"desktop-pause-icon\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" class=\"desktop-play-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"6,4 20,12 6,20\"/>\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 <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 </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 ").concat(this.infoButton('ttp-info-btn--onctrl'), "\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 secondary\" id=\"desktopPauseBtnCompact\" title=\"Pause call\" aria-label=\"Pause call\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" class=\"desktop-pause-icon\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\" stroke=\"none\" class=\"desktop-play-icon\" style=\"display: none; position: absolute;\">\n <polygon points=\"6,4 20,12 6,20\"/>\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 <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 </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\" dir=\"").concat(transcriptDir, "\">\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(transcriptDir, "\">\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(voiceInputDir, "\" 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>");
|
|
40361
41312
|
}
|
|
40362
41313
|
|
|
40363
41314
|
/**
|
|
@@ -40374,7 +41325,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40374
41325
|
var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
|
|
40375
41326
|
var mobileAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"voice-avatar-img\" />") : '🤖';
|
|
40376
41327
|
var mobileAvatarClass = headerAvatarUrl ? 'voice-avatar voice-avatar--image' : 'voice-avatar';
|
|
40377
|
-
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
|
|
41328
|
+
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 ").concat(this.infoButton('ttp-info-btn--floating'), "\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 ").concat(this.infoButton('ttp-info-btn--onbadge'), "\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(7).fill(0).map(function (_, i) {
|
|
40378
41329
|
return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
|
|
40379
41330
|
}).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=\"mobilePauseBtn\" aria-label=\"Pause call\">\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"2\" class=\"mobile-pause-icon\">\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" rx=\"1\"/>\n </svg>\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"#fff\" stroke=\"none\" class=\"mobile-play-icon\" style=\"display: none;\">\n <polygon points=\"6,4 20,12 6,20\"/>\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(transcriptDir, "\">").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(voiceInputDir, "\"\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>");
|
|
40380
41331
|
}
|
|
@@ -41219,7 +42170,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41219
42170
|
"typeMessage": "Type your message...",
|
|
41220
42171
|
"sendMessageAria": "Send message",
|
|
41221
42172
|
"domainNotValidated": "Domain not validated",
|
|
41222
|
-
"domainErrorMessage": "This domain is not whitelisted. Please contact the administrator to whitelist your website URL."
|
|
42173
|
+
"domainErrorMessage": "This domain is not whitelisted. Please contact the administrator to whitelist your website URL.",
|
|
42174
|
+
"aboutTitle": "About",
|
|
42175
|
+
"aboutVersion": "SDK version",
|
|
42176
|
+
"aboutConversationId": "Last conversation ID",
|
|
42177
|
+
"aboutNoConversation": "No conversation yet"
|
|
41223
42178
|
},
|
|
41224
42179
|
"he": {
|
|
41225
42180
|
"landingTitle": "איך תרצה לתקשר?",
|
|
@@ -41252,7 +42207,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41252
42207
|
"typeMessage": "הקלד הודעה...",
|
|
41253
42208
|
"sendMessageAria": "שלח הודעה",
|
|
41254
42209
|
"domainNotValidated": "דומיין לא מאומת",
|
|
41255
|
-
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה."
|
|
42210
|
+
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה.",
|
|
42211
|
+
"aboutTitle": "אודות",
|
|
42212
|
+
"aboutVersion": "גרסת SDK",
|
|
42213
|
+
"aboutConversationId": "מזהה שיחה אחרון",
|
|
42214
|
+
"aboutNoConversation": "אין שיחה עדיין"
|
|
41256
42215
|
},
|
|
41257
42216
|
"ar": {
|
|
41258
42217
|
"landingTitle": "كيف تريد التواصل؟",
|
|
@@ -41285,7 +42244,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41285
42244
|
"typeMessage": "اكتب رسالة...",
|
|
41286
42245
|
"sendMessageAria": "إرسال رسالة",
|
|
41287
42246
|
"domainNotValidated": "النطاق غير معتمد",
|
|
41288
|
-
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة."
|
|
42247
|
+
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة.",
|
|
42248
|
+
"aboutTitle": "حول",
|
|
42249
|
+
"aboutVersion": "إصدار SDK",
|
|
42250
|
+
"aboutConversationId": "معرّف آخر محادثة",
|
|
42251
|
+
"aboutNoConversation": "لا توجد محادثة بعد"
|
|
41289
42252
|
},
|
|
41290
42253
|
"ru": {
|
|
41291
42254
|
"landingTitle": "Как вы хотите общаться?",
|
|
@@ -41318,7 +42281,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41318
42281
|
"typeMessage": "Введите сообщение...",
|
|
41319
42282
|
"sendMessageAria": "Отправить сообщение",
|
|
41320
42283
|
"domainNotValidated": "Домен не проверен",
|
|
41321
|
-
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список."
|
|
42284
|
+
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список.",
|
|
42285
|
+
"aboutTitle": "О приложении",
|
|
42286
|
+
"aboutVersion": "Версия SDK",
|
|
42287
|
+
"aboutConversationId": "ID последнего разговора",
|
|
42288
|
+
"aboutNoConversation": "Разговоров пока нет"
|
|
41322
42289
|
},
|
|
41323
42290
|
"es": {
|
|
41324
42291
|
"landingTitle": "¿Cómo te gustaría comunicarte?",
|
|
@@ -41351,7 +42318,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41351
42318
|
"typeMessage": "Escribe un mensaje...",
|
|
41352
42319
|
"sendMessageAria": "Enviar mensaje",
|
|
41353
42320
|
"domainNotValidated": "Dominio no validado",
|
|
41354
|
-
"domainErrorMessage": "Este dominio no está en la lista blanca. Por favor, contacte al administrador para agregar la URL de su sitio web a la lista."
|
|
42321
|
+
"domainErrorMessage": "Este dominio no está en la lista blanca. Por favor, contacte al administrador para agregar la URL de su sitio web a la lista.",
|
|
42322
|
+
"aboutTitle": "Acerca de",
|
|
42323
|
+
"aboutVersion": "Versión del SDK",
|
|
42324
|
+
"aboutConversationId": "ID de última conversación",
|
|
42325
|
+
"aboutNoConversation": "Aún no hay conversación"
|
|
41355
42326
|
},
|
|
41356
42327
|
"fr": {
|
|
41357
42328
|
"landingTitle": "Comment souhaitez-vous communiquer?",
|
|
@@ -41384,7 +42355,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41384
42355
|
"typeMessage": "Tapez votre message...",
|
|
41385
42356
|
"sendMessageAria": "Envoyer un message",
|
|
41386
42357
|
"domainNotValidated": "Domaine non validé",
|
|
41387
|
-
"domainErrorMessage": "Ce domaine n'est pas sur la liste blanche. Veuillez contacter l'administrateur pour ajouter l'URL de votre site Web à la liste."
|
|
42358
|
+
"domainErrorMessage": "Ce domaine n'est pas sur la liste blanche. Veuillez contacter l'administrateur pour ajouter l'URL de votre site Web à la liste.",
|
|
42359
|
+
"aboutTitle": "À propos",
|
|
42360
|
+
"aboutVersion": "Version du SDK",
|
|
42361
|
+
"aboutConversationId": "ID de la dernière conversation",
|
|
42362
|
+
"aboutNoConversation": "Aucune conversation pour l'instant"
|
|
41388
42363
|
},
|
|
41389
42364
|
"de": {
|
|
41390
42365
|
"landingTitle": "Wie möchten Sie kommunizieren?",
|
|
@@ -41417,7 +42392,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41417
42392
|
"typeMessage": "Geben Sie eine Nachricht ein...",
|
|
41418
42393
|
"sendMessageAria": "Nachricht senden",
|
|
41419
42394
|
"domainNotValidated": "Domain nicht validiert",
|
|
41420
|
-
"domainErrorMessage": "Diese Domain steht nicht auf der Whitelist. Bitte kontaktieren Sie den Administrator, um die URL Ihrer Website zur Liste hinzuzufügen."
|
|
42395
|
+
"domainErrorMessage": "Diese Domain steht nicht auf der Whitelist. Bitte kontaktieren Sie den Administrator, um die URL Ihrer Website zur Liste hinzuzufügen.",
|
|
42396
|
+
"aboutTitle": "Über",
|
|
42397
|
+
"aboutVersion": "SDK-Version",
|
|
42398
|
+
"aboutConversationId": "Letzte Konversations-ID",
|
|
42399
|
+
"aboutNoConversation": "Noch keine Konversation"
|
|
41421
42400
|
}
|
|
41422
42401
|
});
|
|
41423
42402
|
|