ttp-agent-sdk 2.45.7 → 2.45.12
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 +1336 -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-28T10:02:02.645Z";
|
|
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.12";
|
|
20307
|
+
var BUILD_TIME = "2026-06-28T10:02:02.645Z";
|
|
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,32 @@ 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, ")"));
|
|
24862
25066
|
_this4.pendingSentenceText = null;
|
|
24863
25067
|
_this4.pendingSynced = null;
|
|
25068
|
+
_this4.pendingSegmentId = null;
|
|
24864
25069
|
|
|
24865
25070
|
// Start checker if not running
|
|
24866
25071
|
if (!_this4.isCheckingTranscripts) {
|
|
24867
25072
|
_this4.startTranscriptChecker();
|
|
24868
25073
|
}
|
|
25074
|
+
} else if (_this4.sentenceTimings.length > 0) {
|
|
25075
|
+
// Subsequent chunk of the current segment: extend its end on the audio clock.
|
|
25076
|
+
_this4.sentenceTimings[_this4.sentenceTimings.length - 1].endTime = segFrameEnd;
|
|
24869
25077
|
}
|
|
24870
25078
|
|
|
24871
25079
|
// Schedule this chunk to start at nextStartTime
|
|
@@ -24920,8 +25128,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24920
25128
|
if (_this4.scheduledBuffers === 0 && _this4.preparedBuffer.length === 0 && _this4.pcmChunkQueue.length === 0 && !_this4._isStopped) {
|
|
24921
25129
|
_this4.isPlaying = false;
|
|
24922
25130
|
_this4.isSchedulingFrames = false;
|
|
24923
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished)');
|
|
24924
|
-
_this4.emit('playbackStopped'
|
|
25131
|
+
console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished, segmentId: ' + _this4.currentSegmentId + ')');
|
|
25132
|
+
_this4.emit('playbackStopped', {
|
|
25133
|
+
segmentId: _this4.currentSegmentId
|
|
25134
|
+
});
|
|
24925
25135
|
} else if (_this4.preparedBuffer.length > 0 && !_this4._isStopped) {
|
|
24926
25136
|
// More frames available, schedule them immediately
|
|
24927
25137
|
|
|
@@ -24957,8 +25167,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24957
25167
|
};
|
|
24958
25168
|
if (!_this4.isPlaying) {
|
|
24959
25169
|
_this4.isPlaying = true;
|
|
24960
|
-
console.log('🎵 AudioPlayer: Emitting playbackStarted event');
|
|
24961
|
-
_this4.emit('playbackStarted'
|
|
25170
|
+
console.log('🎵 AudioPlayer: Emitting playbackStarted event (segmentId: ' + _this4.currentSegmentId + ')');
|
|
25171
|
+
_this4.emit('playbackStarted', {
|
|
25172
|
+
segmentId: _this4.currentSegmentId
|
|
25173
|
+
});
|
|
24962
25174
|
}
|
|
24963
25175
|
case 3:
|
|
24964
25176
|
return _context3.a(2);
|
|
@@ -26302,14 +26514,66 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26302
26514
|
// Note: scheduledBuffers was already reset to 0 above when clearing scheduledSources
|
|
26303
26515
|
this.nextStartTime = 0;
|
|
26304
26516
|
|
|
26517
|
+
// Report per-segment completion for the interrupted burst BEFORE clearing timing state.
|
|
26518
|
+
// Audible segment → barged_in (ms heard); scheduled-but-unstarted → interrupted;
|
|
26519
|
+
// already-elapsed but unreported → finished. Plus any pending segment (audio_start arrived
|
|
26520
|
+
// but no chunks scheduled yet) → interrupted.
|
|
26521
|
+
try {
|
|
26522
|
+
var nowTs = this.audioContext ? this.audioContext.currentTime : 0;
|
|
26523
|
+
var _iterator = _createForOfIteratorHelper(this.sentenceTimings),
|
|
26524
|
+
_step;
|
|
26525
|
+
try {
|
|
26526
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
26527
|
+
var timing = _step.value;
|
|
26528
|
+
if (timing.doneReported) continue;
|
|
26529
|
+
timing.doneReported = true;
|
|
26530
|
+
var status = void 0,
|
|
26531
|
+
playedMs = void 0;
|
|
26532
|
+
if (timing.endTime != null && nowTs >= timing.endTime) {
|
|
26533
|
+
status = 'finished';
|
|
26534
|
+
playedMs = Math.round((timing.endTime - timing.startTime) * 1000);
|
|
26535
|
+
} else if (nowTs <= timing.startTime) {
|
|
26536
|
+
status = 'interrupted';
|
|
26537
|
+
playedMs = 0;
|
|
26538
|
+
} else {
|
|
26539
|
+
status = 'barged_in';
|
|
26540
|
+
playedMs = Math.round((nowTs - timing.startTime) * 1000);
|
|
26541
|
+
}
|
|
26542
|
+
this.emit('segmentDone', {
|
|
26543
|
+
segmentId: timing.segmentId,
|
|
26544
|
+
status: status,
|
|
26545
|
+
playedMs: playedMs
|
|
26546
|
+
});
|
|
26547
|
+
}
|
|
26548
|
+
} catch (err) {
|
|
26549
|
+
_iterator.e(err);
|
|
26550
|
+
} finally {
|
|
26551
|
+
_iterator.f();
|
|
26552
|
+
}
|
|
26553
|
+
if (this.pendingSegmentId != null) {
|
|
26554
|
+
this.emit('segmentDone', {
|
|
26555
|
+
segmentId: this.pendingSegmentId,
|
|
26556
|
+
status: 'interrupted',
|
|
26557
|
+
playedMs: 0
|
|
26558
|
+
});
|
|
26559
|
+
}
|
|
26560
|
+
} catch (e) {
|
|
26561
|
+
console.warn('⚠️ AudioPlayer: segmentDone (barge-in) reporting failed:', e && e.message);
|
|
26562
|
+
}
|
|
26563
|
+
// Capture the last segment that was playing for the coarse playbackStopped below
|
|
26564
|
+
// (clearTranscriptState resets currentSegmentId).
|
|
26565
|
+
var stoppedSegmentId = this.currentSegmentId;
|
|
26566
|
+
|
|
26305
26567
|
// Clear transcript state
|
|
26306
26568
|
this.clearTranscriptState();
|
|
26307
26569
|
|
|
26308
26570
|
// Emit stopped event - CRITICAL for barge-in
|
|
26309
26571
|
|
|
26310
26572
|
if (wasPlaying) {
|
|
26311
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called)');
|
|
26312
|
-
this.emit('playbackStopped'
|
|
26573
|
+
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called, segmentId: ' + stoppedSegmentId + ')');
|
|
26574
|
+
this.emit('playbackStopped', {
|
|
26575
|
+
segmentId: stoppedSegmentId
|
|
26576
|
+
});
|
|
26313
26577
|
}
|
|
26314
26578
|
}
|
|
26315
26579
|
|
|
@@ -26319,7 +26583,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26319
26583
|
*/
|
|
26320
26584
|
}, {
|
|
26321
26585
|
key: "markNewSentence",
|
|
26322
|
-
value: function markNewSentence(text, synced) {
|
|
26586
|
+
value: function markNewSentence(text, synced, segmentId) {
|
|
26323
26587
|
var _this0 = this;
|
|
26324
26588
|
var wasStopped = this._isStopped;
|
|
26325
26589
|
var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
|
|
@@ -26364,10 +26628,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26364
26628
|
console.log("\uD83D\uDCDD AudioPlayer: New sentence queued while audio playing - will start after current sentence finishes");
|
|
26365
26629
|
}
|
|
26366
26630
|
|
|
26367
|
-
// Always update pending sentence text
|
|
26631
|
+
// Always update pending sentence text, synced actions (for transcript display), and the
|
|
26632
|
+
// backend-assigned segment id (echoed back on the playback events for this segment).
|
|
26368
26633
|
this.pendingSentenceText = text;
|
|
26369
26634
|
this.pendingSynced = synced || null;
|
|
26370
|
-
|
|
26635
|
+
this.pendingSegmentId = segmentId != null ? segmentId : null;
|
|
26636
|
+
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
26637
|
|
|
26372
26638
|
// CRITICAL: Set timeout to detect empty sentences (audio_start but no chunks)
|
|
26373
26639
|
// This prevents queue blocking if backend sends audio_start but no audio chunks follow
|
|
@@ -26379,6 +26645,18 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26379
26645
|
// Check if this sentence still has no chunks after timeout
|
|
26380
26646
|
if (_this0.pendingSentenceText === sentenceText && _this0.scheduledBuffers === 0 && _this0.preparedBuffer.length === 0 && _this0.pcmChunkQueue.length === 0 && !_this0._isStopped) {
|
|
26381
26647
|
console.warn("\u26A0\uFE0F AudioPlayer: Empty sentence detected after 5s timeout - no chunks received for: \"".concat(sentenceText.substring(0, 40), "...\""));
|
|
26648
|
+
// If this empty sentence carried a segment id, report it done (nothing was heard) and
|
|
26649
|
+
// adopt it as current so the coarse stop below matches the backend's last-sent id.
|
|
26650
|
+
if (_this0.pendingSegmentId != null) {
|
|
26651
|
+
var emptySegId = _this0.pendingSegmentId;
|
|
26652
|
+
_this0.currentSegmentId = emptySegId;
|
|
26653
|
+
_this0.pendingSegmentId = null;
|
|
26654
|
+
_this0.emit('segmentDone', {
|
|
26655
|
+
segmentId: emptySegId,
|
|
26656
|
+
status: 'finished',
|
|
26657
|
+
playedMs: 0
|
|
26658
|
+
});
|
|
26659
|
+
}
|
|
26382
26660
|
// Clear pending sentence to unblock next sentence
|
|
26383
26661
|
if (_this0.pendingSentenceText === sentenceText) {
|
|
26384
26662
|
_this0.pendingSentenceText = null;
|
|
@@ -26387,7 +26665,9 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26387
26665
|
// Only if we're not currently playing (to avoid interrupting real playback)
|
|
26388
26666
|
if (!_this0.isPlaying && _this0.scheduledSources.size === 0) {
|
|
26389
26667
|
console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
|
|
26390
|
-
_this0.emit('playbackStopped'
|
|
26668
|
+
_this0.emit('playbackStopped', {
|
|
26669
|
+
segmentId: _this0.currentSegmentId
|
|
26670
|
+
});
|
|
26391
26671
|
}
|
|
26392
26672
|
}
|
|
26393
26673
|
_this0._emptySentenceTimeout = null;
|
|
@@ -26407,31 +26687,64 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26407
26687
|
var _checkLoop = function checkLoop() {
|
|
26408
26688
|
if (!_this1.isCheckingTranscripts || !_this1.audioContext) return;
|
|
26409
26689
|
var currentTime = _this1.audioContext.currentTime;
|
|
26410
|
-
var
|
|
26411
|
-
|
|
26690
|
+
var _iterator2 = _createForOfIteratorHelper(_this1.sentenceTimings),
|
|
26691
|
+
_step2;
|
|
26412
26692
|
try {
|
|
26413
|
-
for (
|
|
26414
|
-
var
|
|
26415
|
-
if (!
|
|
26416
|
-
|
|
26693
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
26694
|
+
var _timing = _step2.value;
|
|
26695
|
+
if (!_timing.displayed && _timing.text && currentTime >= _timing.startTime) {
|
|
26696
|
+
_timing.displayed = true;
|
|
26417
26697
|
var eventData = {
|
|
26418
|
-
text:
|
|
26698
|
+
text: _timing.text
|
|
26419
26699
|
};
|
|
26420
|
-
if (
|
|
26421
|
-
eventData.synced =
|
|
26700
|
+
if (_timing.synced) {
|
|
26701
|
+
eventData.synced = _timing.synced;
|
|
26422
26702
|
}
|
|
26423
|
-
console.log("\uD83D\uDCDD AudioPlayer: Display transcript at ".concat(currentTime.toFixed(3), "s: \"").concat(
|
|
26703
|
+
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
26704
|
_this1.emit('transcriptDisplay', eventData);
|
|
26425
26705
|
}
|
|
26706
|
+
// Per-segment natural finish: this segment's audio window has fully elapsed.
|
|
26707
|
+
if (!_timing.doneReported && _timing.endTime != null && currentTime >= _timing.endTime) {
|
|
26708
|
+
_timing.doneReported = true;
|
|
26709
|
+
var _playedMs = Math.round((_timing.endTime - _timing.startTime) * 1000);
|
|
26710
|
+
_this1.emit('segmentDone', {
|
|
26711
|
+
segmentId: _timing.segmentId,
|
|
26712
|
+
status: 'finished',
|
|
26713
|
+
playedMs: _playedMs
|
|
26714
|
+
});
|
|
26715
|
+
}
|
|
26426
26716
|
}
|
|
26427
26717
|
} catch (err) {
|
|
26428
|
-
|
|
26718
|
+
_iterator2.e(err);
|
|
26429
26719
|
} finally {
|
|
26430
|
-
|
|
26720
|
+
_iterator2.f();
|
|
26431
26721
|
}
|
|
26432
26722
|
if (_this1.isPlaying || _this1.scheduledBuffers > 0) {
|
|
26433
26723
|
requestAnimationFrame(_checkLoop);
|
|
26434
26724
|
} else {
|
|
26725
|
+
// Playback drained naturally — flush any segment whose finish tick we may have missed
|
|
26726
|
+
// (the last buffer's onended can flip isPlaying=false before this loop's next tick).
|
|
26727
|
+
var _iterator3 = _createForOfIteratorHelper(_this1.sentenceTimings),
|
|
26728
|
+
_step3;
|
|
26729
|
+
try {
|
|
26730
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
26731
|
+
var timing = _step3.value;
|
|
26732
|
+
if (!timing.doneReported) {
|
|
26733
|
+
timing.doneReported = true;
|
|
26734
|
+
var end = timing.endTime != null ? timing.endTime : timing.startTime;
|
|
26735
|
+
var playedMs = Math.round((end - timing.startTime) * 1000);
|
|
26736
|
+
_this1.emit('segmentDone', {
|
|
26737
|
+
segmentId: timing.segmentId,
|
|
26738
|
+
status: 'finished',
|
|
26739
|
+
playedMs: playedMs
|
|
26740
|
+
});
|
|
26741
|
+
}
|
|
26742
|
+
}
|
|
26743
|
+
} catch (err) {
|
|
26744
|
+
_iterator3.e(err);
|
|
26745
|
+
} finally {
|
|
26746
|
+
_iterator3.f();
|
|
26747
|
+
}
|
|
26435
26748
|
_this1.isCheckingTranscripts = false;
|
|
26436
26749
|
console.log('📝 AudioPlayer: Transcript checker stopped');
|
|
26437
26750
|
}
|
|
@@ -26447,6 +26760,8 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26447
26760
|
value: function clearTranscriptState() {
|
|
26448
26761
|
this.pendingSentenceText = null;
|
|
26449
26762
|
this.pendingSynced = null;
|
|
26763
|
+
this.pendingSegmentId = null;
|
|
26764
|
+
this.currentSegmentId = null;
|
|
26450
26765
|
this.sentenceTimings = [];
|
|
26451
26766
|
this.isCheckingTranscripts = false;
|
|
26452
26767
|
console.log('📝 AudioPlayer: Transcript state cleared');
|
|
@@ -26596,13 +26911,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26596
26911
|
/* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
|
|
26597
26912
|
/* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
|
|
26598
26913
|
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); }
|
|
26914
|
+
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; } } }; }
|
|
26915
|
+
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; } }
|
|
26916
|
+
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
26917
|
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
26918
|
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
26919
|
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
26920
|
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
26921
|
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
26922
|
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
26923
|
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
@@ -27169,19 +27484,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27169
27484
|
key: "setupAudioPlayerEvents",
|
|
27170
27485
|
value: function setupAudioPlayerEvents() {
|
|
27171
27486
|
var _this3 = this;
|
|
27172
|
-
this.audioPlayer.on('playbackStarted', function () {
|
|
27487
|
+
this.audioPlayer.on('playbackStarted', function (info) {
|
|
27173
27488
|
_this3.isPlaying = true;
|
|
27174
27489
|
_this3.emit('playbackStarted');
|
|
27175
27490
|
|
|
27176
27491
|
// Transcripts are displayed when they arrive (between sentences)
|
|
27177
27492
|
// No need to handle transcript display here - it's handled in handleTranscript()
|
|
27178
27493
|
|
|
27179
|
-
// Notify server - CRITICAL for barge-in detection
|
|
27494
|
+
// Notify server - CRITICAL for barge-in detection.
|
|
27495
|
+
// Carry the segmentId of the burst that started playing (echoed from audio_start) so the
|
|
27496
|
+
// backend can correlate playback events with the bursts it sent.
|
|
27180
27497
|
|
|
27181
27498
|
if (_this3.isConnected) {
|
|
27182
|
-
|
|
27499
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27500
|
+
console.log('📤 VoiceSDK v2: Sending audio_started_playing message to server (segmentId: ' + segmentId + ')');
|
|
27183
27501
|
_this3.sendMessage({
|
|
27184
|
-
t: 'audio_started_playing'
|
|
27502
|
+
t: 'audio_started_playing',
|
|
27503
|
+
segmentId: segmentId
|
|
27185
27504
|
});
|
|
27186
27505
|
} else {
|
|
27187
27506
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_started_playing - not connected');
|
|
@@ -27205,39 +27524,48 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27205
27524
|
_this3.emit('transcriptDisplay', fullTranscriptData);
|
|
27206
27525
|
_this3.emit('transcript', fullTranscriptData);
|
|
27207
27526
|
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
|
-
}
|
|
27527
|
+
console.log("\uD83D\uDCDD VoiceSDK v2: Dispatching ".concat(transcriptData.synced.length, " synced action(s)"));
|
|
27528
|
+
void _this3._dispatchSyncedActions(transcriptData.synced);
|
|
27221
27529
|
}
|
|
27222
27530
|
});
|
|
27223
|
-
this.audioPlayer.on('playbackStopped', function () {
|
|
27531
|
+
this.audioPlayer.on('playbackStopped', function (info) {
|
|
27224
27532
|
_this3.isPlaying = false;
|
|
27225
27533
|
_this3.emit('playbackStopped');
|
|
27226
27534
|
|
|
27227
27535
|
// When playback stops, keep currentPlayingSentenceId to track which sentence just finished
|
|
27228
27536
|
// The next transcript will arrive between sentences and will be displayed immediately
|
|
27229
27537
|
|
|
27230
|
-
// Notify server - CRITICAL for barge-in detection
|
|
27538
|
+
// Notify server - CRITICAL for barge-in detection.
|
|
27539
|
+
// Carry the segmentId of the last burst that was playing so the backend's idle gate can
|
|
27540
|
+
// match this stop against the last burst it sent (deterministic "fully idle").
|
|
27231
27541
|
|
|
27232
27542
|
if (_this3.isConnected) {
|
|
27233
|
-
|
|
27543
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27544
|
+
console.log('📤 VoiceSDK v2: Sending audio_stopped_playing message to server (segmentId: ' + segmentId + ')');
|
|
27234
27545
|
_this3.sendMessage({
|
|
27235
|
-
t: 'audio_stopped_playing'
|
|
27546
|
+
t: 'audio_stopped_playing',
|
|
27547
|
+
segmentId: segmentId
|
|
27236
27548
|
});
|
|
27237
27549
|
} else {
|
|
27238
27550
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_stopped_playing - not connected');
|
|
27239
27551
|
}
|
|
27240
27552
|
});
|
|
27553
|
+
|
|
27554
|
+
// Per-segment playback completion (finished / barged_in / interrupted) with the ms of THIS
|
|
27555
|
+
// segment actually heard. Additive telemetry alongside the coarse started/stopped events.
|
|
27556
|
+
|
|
27557
|
+
this.audioPlayer.on('segmentDone', function (info) {
|
|
27558
|
+
if (!info) return;
|
|
27559
|
+
if (_this3.isConnected) {
|
|
27560
|
+
console.log('📤 VoiceSDK v2: Sending audio_segment_done (segmentId: ' + info.segmentId + ', status: ' + info.status + ', playedMs: ' + info.playedMs + ')');
|
|
27561
|
+
_this3.sendMessage({
|
|
27562
|
+
t: 'audio_segment_done',
|
|
27563
|
+
segmentId: info.segmentId != null ? info.segmentId : null,
|
|
27564
|
+
status: info.status,
|
|
27565
|
+
playedMs: info.playedMs
|
|
27566
|
+
});
|
|
27567
|
+
}
|
|
27568
|
+
});
|
|
27241
27569
|
this.audioPlayer.on('playbackError', function (error) {
|
|
27242
27570
|
_this3.emit('playbackError', error);
|
|
27243
27571
|
_this3.emit('error', error);
|
|
@@ -27602,7 +27930,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27602
27930
|
|
|
27603
27931
|
// Include SDK build time for debugging
|
|
27604
27932
|
if (true) {
|
|
27605
|
-
helloMessage.lastBuildTime = "2026-06-
|
|
27933
|
+
helloMessage.lastBuildTime = "2026-06-28T10:02:02.645Z";
|
|
27606
27934
|
}
|
|
27607
27935
|
|
|
27608
27936
|
// Page context is intentionally NOT attached to the hello message.
|
|
@@ -27757,7 +28085,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27757
28085
|
case 'audio_start':
|
|
27758
28086
|
// Backend sends audio_start with transcript text before audio chunks
|
|
27759
28087
|
// 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);
|
|
28088
|
+
console.log('📝 VoiceSDK v2: Received audio_start with text:', message.text, '(segmentId:', message.segmentId, ')');
|
|
27761
28089
|
|
|
27762
28090
|
// CRITICAL: Record timestamp to prevent premature stop_playing messages from cutting sentences
|
|
27763
28091
|
this.lastAudioStartTime = Date.now();
|
|
@@ -27773,7 +28101,10 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27773
28101
|
if (synced) {
|
|
27774
28102
|
console.log("\uD83D\uDCDD VoiceSDK v2: audio_start carries ".concat(synced.length, " synced action(s)"));
|
|
27775
28103
|
}
|
|
27776
|
-
|
|
28104
|
+
// Pass the backend-assigned segmentId (may be undefined for legacy backends) so the
|
|
28105
|
+
// player can echo it back on this segment's playback events.
|
|
28106
|
+
var segmentId = message.segmentId != null ? message.segmentId : null;
|
|
28107
|
+
this.audioPlayer.markNewSentence(message.text, synced, segmentId);
|
|
27777
28108
|
}
|
|
27778
28109
|
// Also emit as message for other listeners
|
|
27779
28110
|
this.emit('message', message);
|
|
@@ -28302,6 +28633,104 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28302
28633
|
}
|
|
28303
28634
|
}
|
|
28304
28635
|
|
|
28636
|
+
/**
|
|
28637
|
+
* Dispatch widget actions synced to a TTS sentence boundary.
|
|
28638
|
+
* run_partner_script envelopes must go through the same handler as WS traffic
|
|
28639
|
+
* (show_media and other t= messages still emit as generic message events).
|
|
28640
|
+
* @private
|
|
28641
|
+
*/
|
|
28642
|
+
}, {
|
|
28643
|
+
key: "_dispatchSyncedActions",
|
|
28644
|
+
value: (function () {
|
|
28645
|
+
var _dispatchSyncedActions2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(actions) {
|
|
28646
|
+
var _iterator, _step, raw, _t2;
|
|
28647
|
+
return _regenerator().w(function (_context3) {
|
|
28648
|
+
while (1) switch (_context3.p = _context3.n) {
|
|
28649
|
+
case 0:
|
|
28650
|
+
_iterator = _createForOfIteratorHelper(actions);
|
|
28651
|
+
_context3.p = 1;
|
|
28652
|
+
_iterator.s();
|
|
28653
|
+
case 2:
|
|
28654
|
+
if ((_step = _iterator.n()).done) {
|
|
28655
|
+
_context3.n = 4;
|
|
28656
|
+
break;
|
|
28657
|
+
}
|
|
28658
|
+
raw = _step.value;
|
|
28659
|
+
_context3.n = 3;
|
|
28660
|
+
return this._dispatchSyncedAction(raw);
|
|
28661
|
+
case 3:
|
|
28662
|
+
_context3.n = 2;
|
|
28663
|
+
break;
|
|
28664
|
+
case 4:
|
|
28665
|
+
_context3.n = 6;
|
|
28666
|
+
break;
|
|
28667
|
+
case 5:
|
|
28668
|
+
_context3.p = 5;
|
|
28669
|
+
_t2 = _context3.v;
|
|
28670
|
+
_iterator.e(_t2);
|
|
28671
|
+
case 6:
|
|
28672
|
+
_context3.p = 6;
|
|
28673
|
+
_iterator.f();
|
|
28674
|
+
return _context3.f(6);
|
|
28675
|
+
case 7:
|
|
28676
|
+
return _context3.a(2);
|
|
28677
|
+
}
|
|
28678
|
+
}, _callee3, this, [[1, 5, 6, 7]]);
|
|
28679
|
+
}));
|
|
28680
|
+
function _dispatchSyncedActions(_x) {
|
|
28681
|
+
return _dispatchSyncedActions2.apply(this, arguments);
|
|
28682
|
+
}
|
|
28683
|
+
return _dispatchSyncedActions;
|
|
28684
|
+
}())
|
|
28685
|
+
}, {
|
|
28686
|
+
key: "_dispatchSyncedAction",
|
|
28687
|
+
value: function () {
|
|
28688
|
+
var _dispatchSyncedAction2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(action) {
|
|
28689
|
+
var message, _t3;
|
|
28690
|
+
return _regenerator().w(function (_context4) {
|
|
28691
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
28692
|
+
case 0:
|
|
28693
|
+
message = action;
|
|
28694
|
+
if (!(typeof message === 'string')) {
|
|
28695
|
+
_context4.n = 3;
|
|
28696
|
+
break;
|
|
28697
|
+
}
|
|
28698
|
+
_context4.p = 1;
|
|
28699
|
+
message = JSON.parse(message);
|
|
28700
|
+
_context4.n = 3;
|
|
28701
|
+
break;
|
|
28702
|
+
case 2:
|
|
28703
|
+
_context4.p = 2;
|
|
28704
|
+
_t3 = _context4.v;
|
|
28705
|
+
console.warn('⚠️ VoiceSDK v2: Ignoring invalid synced action string:', action);
|
|
28706
|
+
return _context4.a(2);
|
|
28707
|
+
case 3:
|
|
28708
|
+
if (!(!message || _typeof(message) !== 'object')) {
|
|
28709
|
+
_context4.n = 4;
|
|
28710
|
+
break;
|
|
28711
|
+
}
|
|
28712
|
+
return _context4.a(2);
|
|
28713
|
+
case 4:
|
|
28714
|
+
if (!(message.t === 'run_partner_script')) {
|
|
28715
|
+
_context4.n = 6;
|
|
28716
|
+
break;
|
|
28717
|
+
}
|
|
28718
|
+
_context4.n = 5;
|
|
28719
|
+
return this._handleRunPartnerScript(message);
|
|
28720
|
+
case 5:
|
|
28721
|
+
return _context4.a(2);
|
|
28722
|
+
case 6:
|
|
28723
|
+
this.emit('message', message);
|
|
28724
|
+
case 7:
|
|
28725
|
+
return _context4.a(2);
|
|
28726
|
+
}
|
|
28727
|
+
}, _callee4, this, [[1, 2]]);
|
|
28728
|
+
}));
|
|
28729
|
+
function _dispatchSyncedAction(_x2) {
|
|
28730
|
+
return _dispatchSyncedAction2.apply(this, arguments);
|
|
28731
|
+
}
|
|
28732
|
+
return _dispatchSyncedAction;
|
|
28733
|
+
}()
|
|
28305
28734
|
/**
|
|
28306
28735
|
* Handle a run_partner_script envelope (async partner-adapter dispatch).
|
|
28307
28736
|
*
|
|
@@ -28320,30 +28749,30 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28320
28749
|
}, {
|
|
28321
28750
|
key: "_handleRunPartnerScript",
|
|
28322
28751
|
value: (function () {
|
|
28323
|
-
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28752
|
+
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(message) {
|
|
28324
28753
|
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 (
|
|
28754
|
+
var _ref, requestId, partnerId, action, args, handler, startedAt, result, elapsedMs, ok, reason, extras, preview, _elapsedMs, _t4;
|
|
28755
|
+
return _regenerator().w(function (_context5) {
|
|
28756
|
+
while (1) switch (_context5.p = _context5.n) {
|
|
28328
28757
|
case 0:
|
|
28329
28758
|
_ref = message || {}, requestId = _ref.requestId, partnerId = _ref.partnerId, action = _ref.action;
|
|
28330
28759
|
args = message && message.args || {};
|
|
28331
28760
|
if (requestId) {
|
|
28332
|
-
|
|
28761
|
+
_context5.n = 1;
|
|
28333
28762
|
break;
|
|
28334
28763
|
}
|
|
28335
28764
|
console.warn('⚠️ VoiceSDK v2: run_partner_script missing requestId; dropping', message);
|
|
28336
|
-
return
|
|
28765
|
+
return _context5.a(2);
|
|
28337
28766
|
case 1:
|
|
28338
28767
|
if (!_core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__.ClientScriptManager.isClientToolsScript(message)) {
|
|
28339
|
-
|
|
28768
|
+
_context5.n = 2;
|
|
28340
28769
|
break;
|
|
28341
28770
|
}
|
|
28342
|
-
return
|
|
28771
|
+
return _context5.a(2, this.clientScriptManager.handleRunPartnerScript(message));
|
|
28343
28772
|
case 2:
|
|
28344
28773
|
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
28774
|
if (handler) {
|
|
28346
|
-
|
|
28775
|
+
_context5.n = 3;
|
|
28347
28776
|
break;
|
|
28348
28777
|
}
|
|
28349
28778
|
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 +28784,18 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28355
28784
|
ok: false,
|
|
28356
28785
|
error: 'no_handler_registered'
|
|
28357
28786
|
});
|
|
28358
|
-
return
|
|
28787
|
+
return _context5.a(2);
|
|
28359
28788
|
case 3:
|
|
28360
28789
|
startedAt = Date.now();
|
|
28361
28790
|
console.log("\uD83E\uDDE9 VoiceSDK v2: run_partner_script dispatch partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId));
|
|
28362
|
-
|
|
28363
|
-
|
|
28791
|
+
_context5.p = 4;
|
|
28792
|
+
_context5.n = 5;
|
|
28364
28793
|
return handler({
|
|
28365
28794
|
action: action,
|
|
28366
28795
|
args: args
|
|
28367
28796
|
});
|
|
28368
28797
|
case 5:
|
|
28369
|
-
result =
|
|
28798
|
+
result = _context5.v;
|
|
28370
28799
|
elapsedMs = Date.now() - startedAt; // Adapters return { ok, ... } themselves. Honor that flag if present;
|
|
28371
28800
|
// otherwise treat presence-of-result as success.
|
|
28372
28801
|
ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; // Surface the failure reason inline so debugging doesn't require pulling
|
|
@@ -28393,27 +28822,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28393
28822
|
ok: ok,
|
|
28394
28823
|
result: result
|
|
28395
28824
|
});
|
|
28396
|
-
|
|
28825
|
+
_context5.n = 7;
|
|
28397
28826
|
break;
|
|
28398
28827
|
case 6:
|
|
28399
|
-
|
|
28400
|
-
|
|
28828
|
+
_context5.p = 6;
|
|
28829
|
+
_t4 = _context5.v;
|
|
28401
28830
|
_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):"),
|
|
28831
|
+
console.error("\uD83E\uDDE9 VoiceSDK v2: run_partner_script threw partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId, " (").concat(_elapsedMs, "ms):"), _t4);
|
|
28403
28832
|
this.sendMessage({
|
|
28404
28833
|
t: 'run_partner_script_result',
|
|
28405
28834
|
requestId: requestId,
|
|
28406
28835
|
partnerId: partnerId,
|
|
28407
28836
|
action: action,
|
|
28408
28837
|
ok: false,
|
|
28409
|
-
error:
|
|
28838
|
+
error: _t4 && _t4.message || String(_t4)
|
|
28410
28839
|
});
|
|
28411
28840
|
case 7:
|
|
28412
|
-
return
|
|
28841
|
+
return _context5.a(2);
|
|
28413
28842
|
}
|
|
28414
|
-
},
|
|
28843
|
+
}, _callee5, this, [[4, 6]]);
|
|
28415
28844
|
}));
|
|
28416
|
-
function _handleRunPartnerScript(
|
|
28845
|
+
function _handleRunPartnerScript(_x3) {
|
|
28417
28846
|
return _handleRunPartnerScript2.apply(this, arguments);
|
|
28418
28847
|
}
|
|
28419
28848
|
return _handleRunPartnerScript;
|
|
@@ -28458,7 +28887,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28458
28887
|
}, {
|
|
28459
28888
|
key: "injectData",
|
|
28460
28889
|
value: (function () {
|
|
28461
|
-
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28890
|
+
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
28462
28891
|
var _this7 = this;
|
|
28463
28892
|
var options,
|
|
28464
28893
|
trimmedData,
|
|
@@ -28469,15 +28898,15 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28469
28898
|
timeout,
|
|
28470
28899
|
source,
|
|
28471
28900
|
message,
|
|
28472
|
-
|
|
28473
|
-
return _regenerator().w(function (
|
|
28474
|
-
while (1) switch (
|
|
28901
|
+
_args6 = arguments;
|
|
28902
|
+
return _regenerator().w(function (_context6) {
|
|
28903
|
+
while (1) switch (_context6.n) {
|
|
28475
28904
|
case 0:
|
|
28476
|
-
options =
|
|
28905
|
+
options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
|
|
28477
28906
|
// Validation: data content
|
|
28478
28907
|
trimmedData = data === null || data === void 0 ? void 0 : data.trim();
|
|
28479
28908
|
if (trimmedData) {
|
|
28480
|
-
|
|
28909
|
+
_context6.n = 1;
|
|
28481
28910
|
break;
|
|
28482
28911
|
}
|
|
28483
28912
|
error = {
|
|
@@ -28489,7 +28918,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28489
28918
|
throw new Error(error.message);
|
|
28490
28919
|
case 1:
|
|
28491
28920
|
if (!(!this.isConnected || !this.websocket)) {
|
|
28492
|
-
|
|
28921
|
+
_context6.n = 2;
|
|
28493
28922
|
break;
|
|
28494
28923
|
}
|
|
28495
28924
|
_error = {
|
|
@@ -28501,7 +28930,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28501
28930
|
throw new Error(_error.message);
|
|
28502
28931
|
case 2:
|
|
28503
28932
|
if (!(trimmedData.length > 5000)) {
|
|
28504
|
-
|
|
28933
|
+
_context6.n = 3;
|
|
28505
28934
|
break;
|
|
28506
28935
|
}
|
|
28507
28936
|
_error2 = {
|
|
@@ -28530,7 +28959,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28530
28959
|
}
|
|
28531
28960
|
|
|
28532
28961
|
// Return Promise that resolves when acknowledgment is received
|
|
28533
|
-
return
|
|
28962
|
+
return _context6.a(2, new Promise(function (_resolve, _reject) {
|
|
28534
28963
|
// Set up timeout
|
|
28535
28964
|
var timeoutId = setTimeout(function () {
|
|
28536
28965
|
// Remove from pending map
|
|
@@ -28581,9 +29010,9 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28581
29010
|
}
|
|
28582
29011
|
}));
|
|
28583
29012
|
}
|
|
28584
|
-
},
|
|
29013
|
+
}, _callee6, this);
|
|
28585
29014
|
}));
|
|
28586
|
-
function injectData(
|
|
29015
|
+
function injectData(_x4) {
|
|
28587
29016
|
return _injectData.apply(this, arguments);
|
|
28588
29017
|
}
|
|
28589
29018
|
return injectData;
|
|
@@ -28713,20 +29142,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28713
29142
|
}, {
|
|
28714
29143
|
key: "handleBinaryMessage",
|
|
28715
29144
|
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 (
|
|
29145
|
+
var _handleBinaryMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(data) {
|
|
29146
|
+
var arrayBuffer, processedAudio, playbackFormat, container, encoding, pcmData, codec, decoded, _t5;
|
|
29147
|
+
return _regenerator().w(function (_context7) {
|
|
29148
|
+
while (1) switch (_context7.p = _context7.n) {
|
|
28720
29149
|
case 0:
|
|
28721
29150
|
if (!(data instanceof Blob)) {
|
|
28722
|
-
|
|
29151
|
+
_context7.n = 2;
|
|
28723
29152
|
break;
|
|
28724
29153
|
}
|
|
28725
|
-
|
|
29154
|
+
_context7.n = 1;
|
|
28726
29155
|
return data.arrayBuffer();
|
|
28727
29156
|
case 1:
|
|
28728
|
-
arrayBuffer =
|
|
28729
|
-
|
|
29157
|
+
arrayBuffer = _context7.v;
|
|
29158
|
+
_context7.n = 3;
|
|
28730
29159
|
break;
|
|
28731
29160
|
case 2:
|
|
28732
29161
|
arrayBuffer = data;
|
|
@@ -28734,21 +29163,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28734
29163
|
// Convert format if needed (before passing to AudioPlayer)
|
|
28735
29164
|
processedAudio = arrayBuffer;
|
|
28736
29165
|
if (!(this.formatConverter && this.formatConverter.needsConversion())) {
|
|
28737
|
-
|
|
29166
|
+
_context7.n = 7;
|
|
28738
29167
|
break;
|
|
28739
29168
|
}
|
|
28740
|
-
|
|
28741
|
-
|
|
29169
|
+
_context7.p = 4;
|
|
29170
|
+
_context7.n = 5;
|
|
28742
29171
|
return this.formatConverter.convert(arrayBuffer);
|
|
28743
29172
|
case 5:
|
|
28744
|
-
processedAudio =
|
|
29173
|
+
processedAudio = _context7.v;
|
|
28745
29174
|
console.log('✅ VoiceSDK v2: Audio converted to requested format');
|
|
28746
|
-
|
|
29175
|
+
_context7.n = 7;
|
|
28747
29176
|
break;
|
|
28748
29177
|
case 6:
|
|
28749
|
-
|
|
28750
|
-
|
|
28751
|
-
console.error('❌ VoiceSDK v2: Format conversion failed:',
|
|
29178
|
+
_context7.p = 6;
|
|
29179
|
+
_t5 = _context7.v;
|
|
29180
|
+
console.error('❌ VoiceSDK v2: Format conversion failed:', _t5);
|
|
28752
29181
|
console.warn(' Using backend format without conversion');
|
|
28753
29182
|
processedAudio = arrayBuffer; // Fall back to original
|
|
28754
29183
|
case 7:
|
|
@@ -28798,11 +29227,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28798
29227
|
this.audioPlayer.playAudio(processedAudio);
|
|
28799
29228
|
}
|
|
28800
29229
|
case 8:
|
|
28801
|
-
return
|
|
29230
|
+
return _context7.a(2);
|
|
28802
29231
|
}
|
|
28803
|
-
},
|
|
29232
|
+
}, _callee7, this, [[4, 6]]);
|
|
28804
29233
|
}));
|
|
28805
|
-
function handleBinaryMessage(
|
|
29234
|
+
function handleBinaryMessage(_x5) {
|
|
28806
29235
|
return _handleBinaryMessage.apply(this, arguments);
|
|
28807
29236
|
}
|
|
28808
29237
|
return handleBinaryMessage;
|
|
@@ -28990,22 +29419,22 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28990
29419
|
}, {
|
|
28991
29420
|
key: "startRecording",
|
|
28992
29421
|
value: (function () {
|
|
28993
|
-
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29422
|
+
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
28994
29423
|
var existingMediaStream,
|
|
28995
29424
|
error,
|
|
28996
29425
|
_error4,
|
|
28997
29426
|
_error5,
|
|
28998
29427
|
permissionError,
|
|
28999
|
-
|
|
29000
|
-
|
|
29001
|
-
|
|
29002
|
-
|
|
29003
|
-
return _regenerator().w(function (
|
|
29004
|
-
while (1) switch (
|
|
29428
|
+
_args8 = arguments,
|
|
29429
|
+
_t6,
|
|
29430
|
+
_t7,
|
|
29431
|
+
_t8;
|
|
29432
|
+
return _regenerator().w(function (_context8) {
|
|
29433
|
+
while (1) switch (_context8.p = _context8.n) {
|
|
29005
29434
|
case 0:
|
|
29006
|
-
existingMediaStream =
|
|
29435
|
+
existingMediaStream = _args8.length > 0 && _args8[0] !== undefined ? _args8[0] : null;
|
|
29007
29436
|
if (this.isConnected) {
|
|
29008
|
-
|
|
29437
|
+
_context8.n = 1;
|
|
29009
29438
|
break;
|
|
29010
29439
|
}
|
|
29011
29440
|
error = new Error('Not connected to voice server');
|
|
@@ -29013,14 +29442,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29013
29442
|
throw error;
|
|
29014
29443
|
case 1:
|
|
29015
29444
|
if (!this.isRecording) {
|
|
29016
|
-
|
|
29445
|
+
_context8.n = 2;
|
|
29017
29446
|
break;
|
|
29018
29447
|
}
|
|
29019
29448
|
console.warn('VoiceSDK v2: Already recording');
|
|
29020
|
-
return
|
|
29449
|
+
return _context8.a(2, true);
|
|
29021
29450
|
case 2:
|
|
29022
29451
|
if (!this.disclaimersPending) {
|
|
29023
|
-
|
|
29452
|
+
_context8.n = 3;
|
|
29024
29453
|
break;
|
|
29025
29454
|
}
|
|
29026
29455
|
_error4 = new Error('Server disclaimers must be accepted before recording. Call sendDisclaimerAck(true) first.');
|
|
@@ -29029,28 +29458,28 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29029
29458
|
throw _error4;
|
|
29030
29459
|
case 3:
|
|
29031
29460
|
console.log('🎤 VoiceSDK v2: Starting recording...');
|
|
29032
|
-
|
|
29461
|
+
_context8.p = 4;
|
|
29033
29462
|
// CRITICAL for mobile browsers: Request microphone permission FIRST
|
|
29034
29463
|
// iOS: Pass existingMediaStream to avoid second getUserMedia (can fail on iOS)
|
|
29035
29464
|
console.log('🎤 VoiceSDK v2: Requesting microphone permission (mobile-friendly)...');
|
|
29036
|
-
|
|
29465
|
+
_context8.n = 5;
|
|
29037
29466
|
return this.audioRecorder.start(existingMediaStream ? {
|
|
29038
29467
|
existingMediaStream: existingMediaStream
|
|
29039
29468
|
} : {});
|
|
29040
29469
|
case 5:
|
|
29041
29470
|
if (!(!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN)) {
|
|
29042
|
-
|
|
29471
|
+
_context8.n = 10;
|
|
29043
29472
|
break;
|
|
29044
29473
|
}
|
|
29045
|
-
|
|
29046
|
-
|
|
29474
|
+
_context8.p = 6;
|
|
29475
|
+
_context8.n = 7;
|
|
29047
29476
|
return this.audioRecorder.stop();
|
|
29048
29477
|
case 7:
|
|
29049
|
-
|
|
29478
|
+
_context8.n = 9;
|
|
29050
29479
|
break;
|
|
29051
29480
|
case 8:
|
|
29052
|
-
|
|
29053
|
-
|
|
29481
|
+
_context8.p = 8;
|
|
29482
|
+
_t6 = _context8.v;
|
|
29054
29483
|
case 9:
|
|
29055
29484
|
_error5 = new Error('Connection lost - server may have rejected the call');
|
|
29056
29485
|
_error5.name = 'ServerRejected';
|
|
@@ -29059,7 +29488,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29059
29488
|
// The error handler in VoiceInterface will handle it appropriately
|
|
29060
29489
|
throw _error5;
|
|
29061
29490
|
case 10:
|
|
29062
|
-
|
|
29491
|
+
_context8.n = 11;
|
|
29063
29492
|
return this.audioPlayer.resumeAudioContext();
|
|
29064
29493
|
case 11:
|
|
29065
29494
|
// After permission is granted, send start_continuous_mode message to server
|
|
@@ -29070,45 +29499,45 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29070
29499
|
|
|
29071
29500
|
// Request screen wake lock to keep screen on during voice call (mobile)
|
|
29072
29501
|
this._requestWakeLock();
|
|
29073
|
-
return
|
|
29502
|
+
return _context8.a(2, true);
|
|
29074
29503
|
case 12:
|
|
29075
|
-
|
|
29076
|
-
|
|
29504
|
+
_context8.p = 12;
|
|
29505
|
+
_t7 = _context8.v;
|
|
29077
29506
|
if (!(this.audioRecorder && this.audioRecorder.isRecording)) {
|
|
29078
|
-
|
|
29507
|
+
_context8.n = 16;
|
|
29079
29508
|
break;
|
|
29080
29509
|
}
|
|
29081
|
-
|
|
29082
|
-
|
|
29510
|
+
_context8.p = 13;
|
|
29511
|
+
_context8.n = 14;
|
|
29083
29512
|
return this.audioRecorder.stop();
|
|
29084
29513
|
case 14:
|
|
29085
|
-
|
|
29514
|
+
_context8.n = 16;
|
|
29086
29515
|
break;
|
|
29087
29516
|
case 15:
|
|
29088
|
-
|
|
29089
|
-
|
|
29517
|
+
_context8.p = 15;
|
|
29518
|
+
_t8 = _context8.v;
|
|
29090
29519
|
case 16:
|
|
29091
|
-
if (!(
|
|
29092
|
-
|
|
29520
|
+
if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
|
|
29521
|
+
_context8.n = 17;
|
|
29093
29522
|
break;
|
|
29094
29523
|
}
|
|
29095
|
-
return
|
|
29524
|
+
return _context8.a(2, false);
|
|
29096
29525
|
case 17:
|
|
29097
29526
|
// Log and emit other errors (permission denied, etc.)
|
|
29098
|
-
console.error('❌ VoiceSDK v2: Failed to start recording:',
|
|
29527
|
+
console.error('❌ VoiceSDK v2: Failed to start recording:', _t7);
|
|
29099
29528
|
|
|
29100
29529
|
// Provide helpful error messages for permission issues
|
|
29101
|
-
if (
|
|
29530
|
+
if (_t7.name === 'NotAllowedError' || _t7.name === 'PermissionDeniedError') {
|
|
29102
29531
|
permissionError = new Error('Microphone permission denied. Please allow microphone access in your browser settings and try again.');
|
|
29103
|
-
permissionError.name =
|
|
29104
|
-
permissionError.originalError =
|
|
29532
|
+
permissionError.name = _t7.name;
|
|
29533
|
+
permissionError.originalError = _t7;
|
|
29105
29534
|
this.emit('error', permissionError);
|
|
29106
29535
|
} else {
|
|
29107
|
-
this.emit('error',
|
|
29536
|
+
this.emit('error', _t7);
|
|
29108
29537
|
}
|
|
29109
|
-
return
|
|
29538
|
+
return _context8.a(2, false);
|
|
29110
29539
|
}
|
|
29111
|
-
},
|
|
29540
|
+
}, _callee8, this, [[13, 15], [6, 8], [4, 12]]);
|
|
29112
29541
|
}));
|
|
29113
29542
|
function startRecording() {
|
|
29114
29543
|
return _startRecording.apply(this, arguments);
|
|
@@ -29122,20 +29551,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29122
29551
|
}, {
|
|
29123
29552
|
key: "stopRecording",
|
|
29124
29553
|
value: (function () {
|
|
29125
|
-
var _stopRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29126
|
-
var
|
|
29127
|
-
return _regenerator().w(function (
|
|
29128
|
-
while (1) switch (
|
|
29554
|
+
var _stopRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
29555
|
+
var _t9;
|
|
29556
|
+
return _regenerator().w(function (_context9) {
|
|
29557
|
+
while (1) switch (_context9.p = _context9.n) {
|
|
29129
29558
|
case 0:
|
|
29130
29559
|
if (this.isRecording) {
|
|
29131
|
-
|
|
29560
|
+
_context9.n = 1;
|
|
29132
29561
|
break;
|
|
29133
29562
|
}
|
|
29134
29563
|
console.warn('VoiceSDK v2: Not recording');
|
|
29135
|
-
return
|
|
29564
|
+
return _context9.a(2, true);
|
|
29136
29565
|
case 1:
|
|
29137
29566
|
console.log('🛑 VoiceSDK v2: Stopping recording...');
|
|
29138
|
-
|
|
29567
|
+
_context9.p = 2;
|
|
29139
29568
|
// Send stop_continuous_mode message to server
|
|
29140
29569
|
|
|
29141
29570
|
this.sendMessage({
|
|
@@ -29153,21 +29582,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29153
29582
|
this._releaseWakeLock();
|
|
29154
29583
|
|
|
29155
29584
|
// Stop capturing audio from microphone
|
|
29156
|
-
|
|
29585
|
+
_context9.n = 3;
|
|
29157
29586
|
return this.audioRecorder.stop();
|
|
29158
29587
|
case 3:
|
|
29159
29588
|
// Stop any playing audio
|
|
29160
29589
|
|
|
29161
29590
|
this.stopAudioPlayback();
|
|
29162
|
-
return
|
|
29591
|
+
return _context9.a(2, true);
|
|
29163
29592
|
case 4:
|
|
29164
|
-
|
|
29165
|
-
|
|
29166
|
-
console.error('VoiceSDK v2: Error stopping recording:',
|
|
29167
|
-
this.emit('error',
|
|
29168
|
-
return
|
|
29593
|
+
_context9.p = 4;
|
|
29594
|
+
_t9 = _context9.v;
|
|
29595
|
+
console.error('VoiceSDK v2: Error stopping recording:', _t9);
|
|
29596
|
+
this.emit('error', _t9);
|
|
29597
|
+
return _context9.a(2, false);
|
|
29169
29598
|
}
|
|
29170
|
-
},
|
|
29599
|
+
}, _callee9, this, [[2, 4]]);
|
|
29171
29600
|
}));
|
|
29172
29601
|
function stopRecording() {
|
|
29173
29602
|
return _stopRecording.apply(this, arguments);
|
|
@@ -29181,27 +29610,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29181
29610
|
}, {
|
|
29182
29611
|
key: "toggleRecording",
|
|
29183
29612
|
value: (function () {
|
|
29184
|
-
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29185
|
-
return _regenerator().w(function (
|
|
29186
|
-
while (1) switch (
|
|
29613
|
+
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
29614
|
+
return _regenerator().w(function (_context0) {
|
|
29615
|
+
while (1) switch (_context0.n) {
|
|
29187
29616
|
case 0:
|
|
29188
29617
|
if (!this.isRecording) {
|
|
29189
|
-
|
|
29618
|
+
_context0.n = 2;
|
|
29190
29619
|
break;
|
|
29191
29620
|
}
|
|
29192
|
-
|
|
29621
|
+
_context0.n = 1;
|
|
29193
29622
|
return this.stopRecording();
|
|
29194
29623
|
case 1:
|
|
29195
|
-
return
|
|
29624
|
+
return _context0.a(2, _context0.v);
|
|
29196
29625
|
case 2:
|
|
29197
|
-
|
|
29626
|
+
_context0.n = 3;
|
|
29198
29627
|
return this.startRecording();
|
|
29199
29628
|
case 3:
|
|
29200
|
-
return
|
|
29629
|
+
return _context0.a(2, _context0.v);
|
|
29201
29630
|
case 4:
|
|
29202
|
-
return
|
|
29631
|
+
return _context0.a(2);
|
|
29203
29632
|
}
|
|
29204
|
-
},
|
|
29633
|
+
}, _callee0, this);
|
|
29205
29634
|
}));
|
|
29206
29635
|
function toggleRecording() {
|
|
29207
29636
|
return _toggleRecording.apply(this, arguments);
|
|
@@ -29232,33 +29661,33 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29232
29661
|
}, {
|
|
29233
29662
|
key: "_requestWakeLock",
|
|
29234
29663
|
value: (function () {
|
|
29235
|
-
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29664
|
+
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
|
|
29236
29665
|
var _this9 = this;
|
|
29237
|
-
var
|
|
29238
|
-
return _regenerator().w(function (
|
|
29239
|
-
while (1) switch (
|
|
29666
|
+
var _t0;
|
|
29667
|
+
return _regenerator().w(function (_context1) {
|
|
29668
|
+
while (1) switch (_context1.p = _context1.n) {
|
|
29240
29669
|
case 0:
|
|
29241
29670
|
if ('wakeLock' in navigator) {
|
|
29242
|
-
|
|
29671
|
+
_context1.n = 1;
|
|
29243
29672
|
break;
|
|
29244
29673
|
}
|
|
29245
29674
|
console.log('📱 VoiceSDK v2: Wake Lock API not available in this browser');
|
|
29246
|
-
return
|
|
29675
|
+
return _context1.a(2);
|
|
29247
29676
|
case 1:
|
|
29248
29677
|
if (!(this.wakeLock !== null || this._wakeLockRequesting)) {
|
|
29249
|
-
|
|
29678
|
+
_context1.n = 2;
|
|
29250
29679
|
break;
|
|
29251
29680
|
}
|
|
29252
29681
|
console.log('📱 VoiceSDK v2: Wake lock already active or being requested');
|
|
29253
|
-
return
|
|
29682
|
+
return _context1.a(2);
|
|
29254
29683
|
case 2:
|
|
29255
|
-
|
|
29684
|
+
_context1.p = 2;
|
|
29256
29685
|
this._wakeLockRequesting = true;
|
|
29257
29686
|
// Request wake lock (screen type keeps screen on)
|
|
29258
|
-
|
|
29687
|
+
_context1.n = 3;
|
|
29259
29688
|
return navigator.wakeLock.request('screen');
|
|
29260
29689
|
case 3:
|
|
29261
|
-
this.wakeLock =
|
|
29690
|
+
this.wakeLock = _context1.v;
|
|
29262
29691
|
console.log('📱 VoiceSDK v2: Screen wake lock activated - screen will stay on during call');
|
|
29263
29692
|
|
|
29264
29693
|
// Handle wake lock release (e.g., user switches tabs, locks device)
|
|
@@ -29266,23 +29695,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29266
29695
|
console.log('📱 VoiceSDK v2: Wake lock released by system');
|
|
29267
29696
|
_this9.wakeLock = null;
|
|
29268
29697
|
});
|
|
29269
|
-
|
|
29698
|
+
_context1.n = 5;
|
|
29270
29699
|
break;
|
|
29271
29700
|
case 4:
|
|
29272
|
-
|
|
29273
|
-
|
|
29701
|
+
_context1.p = 4;
|
|
29702
|
+
_t0 = _context1.v;
|
|
29274
29703
|
// Wake lock request failed (e.g., permission denied, battery saver mode)
|
|
29275
|
-
console.warn('📱 VoiceSDK v2: Failed to request wake lock:',
|
|
29704
|
+
console.warn('📱 VoiceSDK v2: Failed to request wake lock:', _t0.message);
|
|
29276
29705
|
this.wakeLock = null;
|
|
29277
29706
|
// Don't throw - this is a nice-to-have feature, not critical
|
|
29278
29707
|
case 5:
|
|
29279
|
-
|
|
29708
|
+
_context1.p = 5;
|
|
29280
29709
|
this._wakeLockRequesting = false;
|
|
29281
|
-
return
|
|
29710
|
+
return _context1.f(5);
|
|
29282
29711
|
case 6:
|
|
29283
|
-
return
|
|
29712
|
+
return _context1.a(2);
|
|
29284
29713
|
}
|
|
29285
|
-
},
|
|
29714
|
+
}, _callee1, this, [[2, 4, 5, 6]]);
|
|
29286
29715
|
}));
|
|
29287
29716
|
function _requestWakeLock() {
|
|
29288
29717
|
return _requestWakeLock2.apply(this, arguments);
|
|
@@ -29297,34 +29726,34 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29297
29726
|
}, {
|
|
29298
29727
|
key: "_releaseWakeLock",
|
|
29299
29728
|
value: (function () {
|
|
29300
|
-
var _releaseWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29301
|
-
var
|
|
29302
|
-
return _regenerator().w(function (
|
|
29303
|
-
while (1) switch (
|
|
29729
|
+
var _releaseWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
|
|
29730
|
+
var _t1;
|
|
29731
|
+
return _regenerator().w(function (_context10) {
|
|
29732
|
+
while (1) switch (_context10.p = _context10.n) {
|
|
29304
29733
|
case 0:
|
|
29305
29734
|
if (!(this.wakeLock === null)) {
|
|
29306
|
-
|
|
29735
|
+
_context10.n = 1;
|
|
29307
29736
|
break;
|
|
29308
29737
|
}
|
|
29309
|
-
return
|
|
29738
|
+
return _context10.a(2);
|
|
29310
29739
|
case 1:
|
|
29311
|
-
|
|
29312
|
-
|
|
29740
|
+
_context10.p = 1;
|
|
29741
|
+
_context10.n = 2;
|
|
29313
29742
|
return this.wakeLock.release();
|
|
29314
29743
|
case 2:
|
|
29315
29744
|
this.wakeLock = null;
|
|
29316
29745
|
console.log('📱 VoiceSDK v2: Screen wake lock released');
|
|
29317
|
-
|
|
29746
|
+
_context10.n = 4;
|
|
29318
29747
|
break;
|
|
29319
29748
|
case 3:
|
|
29320
|
-
|
|
29321
|
-
|
|
29322
|
-
console.warn('📱 VoiceSDK v2: Error releasing wake lock:',
|
|
29749
|
+
_context10.p = 3;
|
|
29750
|
+
_t1 = _context10.v;
|
|
29751
|
+
console.warn('📱 VoiceSDK v2: Error releasing wake lock:', _t1.message);
|
|
29323
29752
|
this.wakeLock = null;
|
|
29324
29753
|
case 4:
|
|
29325
|
-
return
|
|
29754
|
+
return _context10.a(2);
|
|
29326
29755
|
}
|
|
29327
|
-
},
|
|
29756
|
+
}, _callee10, this, [[1, 3]]);
|
|
29328
29757
|
}));
|
|
29329
29758
|
function _releaseWakeLock() {
|
|
29330
29759
|
return _releaseWakeLock2.apply(this, arguments);
|
|
@@ -29348,21 +29777,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29348
29777
|
}, {
|
|
29349
29778
|
key: "handleBargeIn",
|
|
29350
29779
|
value: (function () {
|
|
29351
|
-
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29352
|
-
return _regenerator().w(function (
|
|
29353
|
-
while (1) switch (
|
|
29780
|
+
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
|
|
29781
|
+
return _regenerator().w(function (_context11) {
|
|
29782
|
+
while (1) switch (_context11.n) {
|
|
29354
29783
|
case 0:
|
|
29355
29784
|
this.stopAudioPlayback();
|
|
29356
29785
|
if (this.isRecording) {
|
|
29357
|
-
|
|
29786
|
+
_context11.n = 1;
|
|
29358
29787
|
break;
|
|
29359
29788
|
}
|
|
29360
|
-
|
|
29789
|
+
_context11.n = 1;
|
|
29361
29790
|
return this.startRecording();
|
|
29362
29791
|
case 1:
|
|
29363
|
-
return
|
|
29792
|
+
return _context11.a(2);
|
|
29364
29793
|
}
|
|
29365
|
-
},
|
|
29794
|
+
}, _callee11, this);
|
|
29366
29795
|
}));
|
|
29367
29796
|
function handleBargeIn() {
|
|
29368
29797
|
return _handleBargeIn.apply(this, arguments);
|
|
@@ -32275,10 +32704,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32275
32704
|
this._flavorObj = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
32276
32705
|
if (this._flavorObj && this._flavorObj.type) {
|
|
32277
32706
|
this._initFlavor(this._flavorObj.type);
|
|
32278
|
-
|
|
32279
|
-
|
|
32707
|
+
} else if (this._flavorObj && !this._flavorObj.type && this._flavorObj.callView !== 'minimized') {
|
|
32708
|
+
// A flavor object with neither a "type" nor callView:'minimized' is malformed.
|
|
32709
|
+
// (callView:'minimized' alone is a valid flavor-less minimized-strip config.)
|
|
32280
32710
|
console.error('[TTPChatWidget] flavor object is set but missing required "type" field. Widget will run in vanilla mode.');
|
|
32281
32711
|
}
|
|
32712
|
+
// The desktop minimized bottom strip is flavor-independent: it only needs
|
|
32713
|
+
// flavor.callView === 'minimized' (+ desktop width). Init it regardless of
|
|
32714
|
+
// whether a flavor type is present, so callView:'minimized' works standalone
|
|
32715
|
+
// with no partner/flavor. _initEcommerceVoiceStrip() self-guards and no-ops
|
|
32716
|
+
// when callView !== 'minimized' or on mobile.
|
|
32717
|
+
this._initEcommerceVoiceStrip();
|
|
32282
32718
|
}
|
|
32283
32719
|
|
|
32284
32720
|
/**
|
|
@@ -32694,7 +33130,11 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32694
33130
|
offset: positionConfig.offset || {
|
|
32695
33131
|
x: 20,
|
|
32696
33132
|
y: 20
|
|
32697
|
-
}
|
|
33133
|
+
},
|
|
33134
|
+
// When true, the launcher pill / mobile FAB can be dragged around the
|
|
33135
|
+
// viewport. Set position.draggablePersist:false to reset position each load.
|
|
33136
|
+
draggable: false,
|
|
33137
|
+
draggablePersist: true
|
|
32698
33138
|
}, _typeof(userConfig.position) === 'object' ? userConfig.position : {}),
|
|
32699
33139
|
// Button Configuration
|
|
32700
33140
|
button: _objectSpread({
|
|
@@ -33330,6 +33770,125 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33330
33770
|
var footer = (_root$querySelector = root.querySelector) === null || _root$querySelector === void 0 ? void 0 : _root$querySelector.call(root, '.ttp-footer');
|
|
33331
33771
|
if (footer) footer.style.display = visible ? '' : 'none';
|
|
33332
33772
|
}
|
|
33773
|
+
|
|
33774
|
+
/**
|
|
33775
|
+
* Resolve the most recent conversation id used by either channel.
|
|
33776
|
+
* Prefers a live voice/text SDK value, then falls back to persisted state.
|
|
33777
|
+
* @returns {string|null}
|
|
33778
|
+
*/
|
|
33779
|
+
}, {
|
|
33780
|
+
key: "_getLastConversationId",
|
|
33781
|
+
value: function _getLastConversationId() {
|
|
33782
|
+
var _this$voiceInterface3, _this$sdk;
|
|
33783
|
+
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;
|
|
33784
|
+
if (live) return live;
|
|
33785
|
+
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;
|
|
33786
|
+
if (textId) return textId;
|
|
33787
|
+
try {
|
|
33788
|
+
var raw = sessionStorage.getItem('voice_resume_state');
|
|
33789
|
+
if (raw) {
|
|
33790
|
+
var s = JSON.parse(raw);
|
|
33791
|
+
if (s && s.conversationId) return s.conversationId;
|
|
33792
|
+
}
|
|
33793
|
+
} catch (_) {/* ignore */}
|
|
33794
|
+
try {
|
|
33795
|
+
var t = localStorage.getItem('ttp_text_chat_conversation_id');
|
|
33796
|
+
if (t) return t;
|
|
33797
|
+
} catch (_) {/* ignore */}
|
|
33798
|
+
return null;
|
|
33799
|
+
}
|
|
33800
|
+
|
|
33801
|
+
/** Inline TalkToPC logo mark (speech bubble + sound waves). */
|
|
33802
|
+
}, {
|
|
33803
|
+
key: "_aboutLogoSVG",
|
|
33804
|
+
value: function _aboutLogoSVG() {
|
|
33805
|
+
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>";
|
|
33806
|
+
}
|
|
33807
|
+
|
|
33808
|
+
/**
|
|
33809
|
+
* Inject the "About" dialog styles into document.head once.
|
|
33810
|
+
* Global (light DOM) so the dialog renders above the desktop minimized strip,
|
|
33811
|
+
* which lives outside the shadow root at the maximum z-index.
|
|
33812
|
+
*/
|
|
33813
|
+
}, {
|
|
33814
|
+
key: "_ensureAboutStyles",
|
|
33815
|
+
value: function _ensureAboutStyles() {
|
|
33816
|
+
if (document.getElementById('ttp-about-dialog-styles')) return;
|
|
33817
|
+
var style = document.createElement('style');
|
|
33818
|
+
style.id = 'ttp-about-dialog-styles';
|
|
33819
|
+
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 ";
|
|
33820
|
+
document.head.appendChild(style);
|
|
33821
|
+
}
|
|
33822
|
+
|
|
33823
|
+
/** Open the shared "About" dialog (logo + SDK version + last conversation id). */
|
|
33824
|
+
}, {
|
|
33825
|
+
key: "_openAboutModal",
|
|
33826
|
+
value: function _openAboutModal() {
|
|
33827
|
+
var _this8 = this,
|
|
33828
|
+
_overlay$querySelecto;
|
|
33829
|
+
// Toggle: if already open, close it.
|
|
33830
|
+
if (this._aboutOverlay) {
|
|
33831
|
+
this._closeAboutModal();
|
|
33832
|
+
return;
|
|
33833
|
+
}
|
|
33834
|
+
this._ensureAboutStyles();
|
|
33835
|
+
var version = true ? "2.45.12" : 0;
|
|
33836
|
+
var convId = this._getLastConversationId();
|
|
33837
|
+
var t = function t(k, fb) {
|
|
33838
|
+
try {
|
|
33839
|
+
var _this8$voiceInterface, _this8$voiceInterface2, _this8$textInterface, _this8$textInterface$;
|
|
33840
|
+
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;
|
|
33841
|
+
} catch (_) {
|
|
33842
|
+
return fb;
|
|
33843
|
+
}
|
|
33844
|
+
};
|
|
33845
|
+
var title = t('aboutTitle', 'About');
|
|
33846
|
+
var versionLabel = t('aboutVersion', 'SDK version');
|
|
33847
|
+
var convLabel = t('aboutConversationId', 'Last conversation ID');
|
|
33848
|
+
var noneLabel = t('aboutNoConversation', 'No conversation yet');
|
|
33849
|
+
var overlay = document.createElement('div');
|
|
33850
|
+
overlay.className = 'ttp-about-overlay';
|
|
33851
|
+
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>");
|
|
33852
|
+
|
|
33853
|
+
// Fill dynamic values via textContent to avoid any injection.
|
|
33854
|
+
var verEl = overlay.querySelector('[data-about-version]');
|
|
33855
|
+
if (verEl) verEl.textContent = version ? "v".concat(version) : '—';
|
|
33856
|
+
var convEl = overlay.querySelector('[data-about-conv]');
|
|
33857
|
+
if (convEl) {
|
|
33858
|
+
convEl.textContent = convId || noneLabel;
|
|
33859
|
+
if (!convId) convEl.classList.add('ttp-about-muted');
|
|
33860
|
+
}
|
|
33861
|
+
var close = function close() {
|
|
33862
|
+
return _this8._closeAboutModal();
|
|
33863
|
+
};
|
|
33864
|
+
overlay.addEventListener('click', function (e) {
|
|
33865
|
+
if (e.target === overlay) close();
|
|
33866
|
+
});
|
|
33867
|
+
(_overlay$querySelecto = overlay.querySelector('.ttp-about-close')) === null || _overlay$querySelecto === void 0 || _overlay$querySelecto.addEventListener('click', function (e) {
|
|
33868
|
+
e.stopPropagation();
|
|
33869
|
+
close();
|
|
33870
|
+
});
|
|
33871
|
+
this._aboutKeyHandler = function (e) {
|
|
33872
|
+
if (e.key === 'Escape') close();
|
|
33873
|
+
};
|
|
33874
|
+
document.addEventListener('keydown', this._aboutKeyHandler);
|
|
33875
|
+
document.body.appendChild(overlay);
|
|
33876
|
+
this._aboutOverlay = overlay;
|
|
33877
|
+
}
|
|
33878
|
+
|
|
33879
|
+
/** Close the "About" dialog if open. */
|
|
33880
|
+
}, {
|
|
33881
|
+
key: "_closeAboutModal",
|
|
33882
|
+
value: function _closeAboutModal() {
|
|
33883
|
+
if (this._aboutKeyHandler) {
|
|
33884
|
+
document.removeEventListener('keydown', this._aboutKeyHandler);
|
|
33885
|
+
this._aboutKeyHandler = null;
|
|
33886
|
+
}
|
|
33887
|
+
if (this._aboutOverlay) {
|
|
33888
|
+
this._aboutOverlay.remove();
|
|
33889
|
+
this._aboutOverlay = null;
|
|
33890
|
+
}
|
|
33891
|
+
}
|
|
33333
33892
|
}, {
|
|
33334
33893
|
key: "generatePositionStyles",
|
|
33335
33894
|
value: function generatePositionStyles() {
|
|
@@ -33461,13 +34020,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33461
34020
|
var callActivePanelBg = callSurfaceGradient;
|
|
33462
34021
|
var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
|
|
33463
34022
|
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 ");
|
|
34023
|
+
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
34024
|
}
|
|
33466
34025
|
}, {
|
|
33467
34026
|
key: "setupWidgetEvents",
|
|
33468
34027
|
value: function setupWidgetEvents() {
|
|
33469
|
-
var
|
|
33470
|
-
_this$config$behavior8
|
|
34028
|
+
var _this9 = this,
|
|
34029
|
+
_this$config$behavior8,
|
|
34030
|
+
_this$config$position5;
|
|
33471
34031
|
if (!this.shadowRoot) return;
|
|
33472
34032
|
|
|
33473
34033
|
// Setup prompt animation visibility and interactions
|
|
@@ -33478,16 +34038,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33478
34038
|
if (launcherBtn) {
|
|
33479
34039
|
launcherBtn.onclick = function (e) {
|
|
33480
34040
|
e.stopPropagation();
|
|
33481
|
-
|
|
33482
|
-
|
|
34041
|
+
// A drag just ended — don't treat the trailing click as "open panel".
|
|
34042
|
+
if (_this9._suppressLauncherClick) return;
|
|
34043
|
+
if (_this9.config.promptAnimation.hideAfterClick) {
|
|
34044
|
+
_this9.hidePrompt();
|
|
33483
34045
|
}
|
|
33484
|
-
|
|
34046
|
+
_this9.togglePanel();
|
|
33485
34047
|
};
|
|
33486
34048
|
}
|
|
33487
34049
|
var closeBtn = this.shadowRoot.getElementById('closeBtn');
|
|
33488
34050
|
if (closeBtn) {
|
|
33489
34051
|
closeBtn.onclick = function () {
|
|
33490
|
-
|
|
34052
|
+
_this9._doTogglePanel();
|
|
33491
34053
|
};
|
|
33492
34054
|
}
|
|
33493
34055
|
|
|
@@ -33495,31 +34057,41 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33495
34057
|
var closeIdle = this.shadowRoot.getElementById('ttpCloseIdle');
|
|
33496
34058
|
if (closeIdle) {
|
|
33497
34059
|
closeIdle.onclick = function () {
|
|
33498
|
-
return
|
|
34060
|
+
return _this9._doTogglePanel();
|
|
33499
34061
|
};
|
|
33500
34062
|
}
|
|
33501
34063
|
var closeActive = this.shadowRoot.getElementById('ttpCloseActive');
|
|
33502
34064
|
if (closeActive) {
|
|
33503
34065
|
closeActive.onclick = function () {
|
|
33504
|
-
return
|
|
34066
|
+
return _this9._doTogglePanel();
|
|
33505
34067
|
};
|
|
33506
34068
|
}
|
|
33507
34069
|
|
|
34070
|
+
// "About" info buttons (present in every view: idle / active / compact /
|
|
34071
|
+
// mobile idle / mobile active / text top-bar). One shared dialog.
|
|
34072
|
+
this.shadowRoot.querySelectorAll('.ttp-info-btn').forEach(function (btn) {
|
|
34073
|
+
btn.onclick = function (e) {
|
|
34074
|
+
e.stopPropagation();
|
|
34075
|
+
e.preventDefault();
|
|
34076
|
+
_this9._openAboutModal();
|
|
34077
|
+
};
|
|
34078
|
+
});
|
|
34079
|
+
|
|
33508
34080
|
// "Send a Message" button in idle view → switch to text interface
|
|
33509
34081
|
var startTextBtn = this.shadowRoot.getElementById('startTextBtn');
|
|
33510
34082
|
if (startTextBtn) {
|
|
33511
34083
|
startTextBtn.onclick = function () {
|
|
33512
|
-
return
|
|
34084
|
+
return _this9.showText();
|
|
33513
34085
|
};
|
|
33514
34086
|
}
|
|
33515
34087
|
var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
|
|
33516
34088
|
if (textUnifiedBackBtn) {
|
|
33517
34089
|
textUnifiedBackBtn.onclick = function () {
|
|
33518
|
-
var
|
|
33519
|
-
var widgetMode = ((
|
|
34090
|
+
var _this9$config$behavio;
|
|
34091
|
+
var widgetMode = ((_this9$config$behavio = _this9.config.behavior) === null || _this9$config$behavio === void 0 ? void 0 : _this9$config$behavio.mode) || 'unified';
|
|
33520
34092
|
if (widgetMode !== 'unified') return;
|
|
33521
|
-
|
|
33522
|
-
|
|
34093
|
+
_this9.showLanding();
|
|
34094
|
+
_this9._openMobileCallTextLanding();
|
|
33523
34095
|
};
|
|
33524
34096
|
}
|
|
33525
34097
|
|
|
@@ -33549,30 +34121,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33549
34121
|
// Setup back button handler
|
|
33550
34122
|
if (backBtn) {
|
|
33551
34123
|
backBtn.onclick = function () {
|
|
33552
|
-
var
|
|
34124
|
+
var _this9$voiceInterface, _this9$voiceInterface3;
|
|
33553
34125
|
// Check if we're showing a domain error — clear it and return to voice hero
|
|
33554
|
-
if ((
|
|
33555
|
-
var
|
|
34126
|
+
if ((_this9$voiceInterface = _this9.voiceInterface) !== null && _this9$voiceInterface !== void 0 && _this9$voiceInterface.isShowingDomainError) {
|
|
34127
|
+
var _this9$voiceInterface2;
|
|
33556
34128
|
console.log('🔙 Back button clicked - clearing domain error and returning to voice hero');
|
|
33557
34129
|
// Clear the domain error flag
|
|
33558
|
-
|
|
34130
|
+
_this9.voiceInterface.isShowingDomainError = false;
|
|
33559
34131
|
// Reset the connecting state (this will restore normal UI)
|
|
33560
|
-
if ((
|
|
33561
|
-
|
|
34132
|
+
if ((_this9$voiceInterface2 = _this9.voiceInterface) !== null && _this9$voiceInterface2 !== void 0 && _this9$voiceInterface2.resetConnectingState) {
|
|
34133
|
+
_this9.voiceInterface.resetConnectingState();
|
|
33562
34134
|
}
|
|
33563
|
-
|
|
33564
|
-
|
|
34135
|
+
_this9.showLanding();
|
|
34136
|
+
_this9._openMobileCallTextLanding();
|
|
33565
34137
|
return;
|
|
33566
34138
|
}
|
|
33567
|
-
if ((
|
|
34139
|
+
if ((_this9$voiceInterface3 = _this9.voiceInterface) !== null && _this9$voiceInterface3 !== void 0 && _this9$voiceInterface3.isActive) {
|
|
33568
34140
|
// If call is active, show message inside widget instead of modal
|
|
33569
|
-
|
|
34141
|
+
_this9.showBackButtonWarning();
|
|
33570
34142
|
} else if (window.innerWidth <= 768) {
|
|
33571
|
-
|
|
33572
|
-
|
|
34143
|
+
_this9.showLanding();
|
|
34144
|
+
_this9._openMobileCallTextLanding();
|
|
33573
34145
|
} else {
|
|
33574
34146
|
// Desktop: return to voice hero (unified home)
|
|
33575
|
-
|
|
34147
|
+
_this9.showLanding();
|
|
33576
34148
|
}
|
|
33577
34149
|
};
|
|
33578
34150
|
}
|
|
@@ -33615,7 +34187,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33615
34187
|
// Setup header button handlers
|
|
33616
34188
|
if (newChatBtn) {
|
|
33617
34189
|
newChatBtn.onclick = function () {
|
|
33618
|
-
return
|
|
34190
|
+
return _this9.textInterface.startNewChat();
|
|
33619
34191
|
};
|
|
33620
34192
|
// Hide new chat on unified home (voice hero) initially
|
|
33621
34193
|
if (isUnified && this.currentView !== 'text') {
|
|
@@ -33626,11 +34198,328 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33626
34198
|
// Mobile floating button & landing overlay
|
|
33627
34199
|
this.setupMobileWidgetEvents();
|
|
33628
34200
|
|
|
34201
|
+
// Optional: make the launcher pill / mobile FAB + the open panel draggable
|
|
34202
|
+
// (they move together as one unit). The minimized strip is wired separately
|
|
34203
|
+
// in _initEcommerceVoiceStrip() since it lives outside the shadow DOM.
|
|
34204
|
+
if ((_this$config$position5 = this.config.position) !== null && _this$config$position5 !== void 0 && _this$config$position5.draggable) {
|
|
34205
|
+
this.setupDraggableWidget();
|
|
34206
|
+
}
|
|
34207
|
+
|
|
33629
34208
|
// Keyboard navigation
|
|
33630
34209
|
if (this.config.accessibility.keyboardNavigation) {
|
|
33631
34210
|
this.setupKeyboardNavigation();
|
|
33632
34211
|
}
|
|
33633
34212
|
}
|
|
34213
|
+
|
|
34214
|
+
/**
|
|
34215
|
+
* Page-scoped namespace for persisted drag positions (origin+path) so the same
|
|
34216
|
+
* widget on different routes keeps independent spots.
|
|
34217
|
+
*/
|
|
34218
|
+
}, {
|
|
34219
|
+
key: "_dragScope",
|
|
34220
|
+
value: function _dragScope() {
|
|
34221
|
+
var scope = '';
|
|
34222
|
+
try {
|
|
34223
|
+
scope = window.location.origin + window.location.pathname;
|
|
34224
|
+
} catch (e) {/* sandboxed */}
|
|
34225
|
+
return scope;
|
|
34226
|
+
}
|
|
34227
|
+
|
|
34228
|
+
/** localStorage key for a dragged surface ('unit' = pill+panel, 'strip'). */
|
|
34229
|
+
}, {
|
|
34230
|
+
key: "_dragStorageKey",
|
|
34231
|
+
value: function _dragStorageKey(kind) {
|
|
34232
|
+
return 'ttp-widget-' + kind + '-pos::' + this._dragScope();
|
|
34233
|
+
}
|
|
34234
|
+
|
|
34235
|
+
/**
|
|
34236
|
+
* The launcher pill and the chat panel move together as one unit. They share a
|
|
34237
|
+
* single translate offset (`this._unitOffset`) so dragging either one (the pill,
|
|
34238
|
+
* the mobile FAB, or a panel header) moves both — they never split apart.
|
|
34239
|
+
*/
|
|
34240
|
+
}, {
|
|
34241
|
+
key: "_unitEls",
|
|
34242
|
+
value: function _unitEls() {
|
|
34243
|
+
var root = this.shadowRoot;
|
|
34244
|
+
if (!root) return [];
|
|
34245
|
+
return [root.getElementById('text-chat-button-container'), root.getElementById('text-chat-panel')].filter(Boolean);
|
|
34246
|
+
}
|
|
34247
|
+
|
|
34248
|
+
/** Apply the shared unit offset as a translate transform to both elements. */
|
|
34249
|
+
}, {
|
|
34250
|
+
key: "_applyUnitOffset",
|
|
34251
|
+
value: function _applyUnitOffset() {
|
|
34252
|
+
var o = this._unitOffset || (this._unitOffset = {
|
|
34253
|
+
x: 0,
|
|
34254
|
+
y: 0
|
|
34255
|
+
});
|
|
34256
|
+
var value = "translate(".concat(o.x, "px, ").concat(o.y, "px)");
|
|
34257
|
+
this._unitEls().forEach(function (el) {
|
|
34258
|
+
return el.style.setProperty('transform', value, 'important');
|
|
34259
|
+
});
|
|
34260
|
+
}
|
|
34261
|
+
|
|
34262
|
+
/**
|
|
34263
|
+
* Base (offset-0) viewport rects of the currently-visible unit elements. The
|
|
34264
|
+
* applied transform equals `this._unitOffset`, so subtracting it recovers the
|
|
34265
|
+
* anchored position. Hidden elements (display:none → 0×0) are skipped.
|
|
34266
|
+
*/
|
|
34267
|
+
}, {
|
|
34268
|
+
key: "_unitBaseRects",
|
|
34269
|
+
value: function _unitBaseRects() {
|
|
34270
|
+
var o = this._unitOffset || {
|
|
34271
|
+
x: 0,
|
|
34272
|
+
y: 0
|
|
34273
|
+
};
|
|
34274
|
+
var rects = [];
|
|
34275
|
+
this._unitEls().forEach(function (el) {
|
|
34276
|
+
var r = el.getBoundingClientRect();
|
|
34277
|
+
if (!r.width && !r.height) return; // hidden
|
|
34278
|
+
rects.push({
|
|
34279
|
+
left: r.left - o.x,
|
|
34280
|
+
top: r.top - o.y,
|
|
34281
|
+
right: r.right - o.x,
|
|
34282
|
+
bottom: r.bottom - o.y
|
|
34283
|
+
});
|
|
34284
|
+
});
|
|
34285
|
+
return rects;
|
|
34286
|
+
}
|
|
34287
|
+
|
|
34288
|
+
/**
|
|
34289
|
+
* Clamp a desired unit offset so every visible unit element stays within the
|
|
34290
|
+
* viewport (8px margin). Constraints from all visible elements are intersected.
|
|
34291
|
+
*/
|
|
34292
|
+
}, {
|
|
34293
|
+
key: "_clampUnitOffset",
|
|
34294
|
+
value: function _clampUnitOffset(x, y, bases) {
|
|
34295
|
+
var margin = 8;
|
|
34296
|
+
var vw = window.innerWidth,
|
|
34297
|
+
vh = window.innerHeight;
|
|
34298
|
+
var minX = -Infinity,
|
|
34299
|
+
maxX = Infinity,
|
|
34300
|
+
minY = -Infinity,
|
|
34301
|
+
maxY = Infinity;
|
|
34302
|
+
bases.forEach(function (b) {
|
|
34303
|
+
minX = Math.max(minX, margin - b.left);
|
|
34304
|
+
maxX = Math.min(maxX, vw - margin - b.right);
|
|
34305
|
+
minY = Math.max(minY, margin - b.top);
|
|
34306
|
+
maxY = Math.min(maxY, vh - margin - b.bottom);
|
|
34307
|
+
});
|
|
34308
|
+
// Element taller/wider than the viewport → keep its top/left edge visible.
|
|
34309
|
+
if (minX > maxX) maxX = minX;
|
|
34310
|
+
if (minY > maxY) maxY = minY;
|
|
34311
|
+
if (!bases.length) return {
|
|
34312
|
+
x: x,
|
|
34313
|
+
y: y
|
|
34314
|
+
};
|
|
34315
|
+
return {
|
|
34316
|
+
x: Math.min(Math.max(x, minX), maxX),
|
|
34317
|
+
y: Math.min(Math.max(y, minY), maxY)
|
|
34318
|
+
};
|
|
34319
|
+
}
|
|
34320
|
+
|
|
34321
|
+
/** Re-clamp the unit to the current viewport (e.g. on resize or panel open). */
|
|
34322
|
+
}, {
|
|
34323
|
+
key: "_reclampUnit",
|
|
34324
|
+
value: function _reclampUnit() {
|
|
34325
|
+
if (!this._unitOffset) return;
|
|
34326
|
+
var bases = this._unitBaseRects();
|
|
34327
|
+
if (!bases.length) return;
|
|
34328
|
+
this._unitOffset = this._clampUnitOffset(this._unitOffset.x, this._unitOffset.y, bases);
|
|
34329
|
+
this._applyUnitOffset();
|
|
34330
|
+
}
|
|
34331
|
+
|
|
34332
|
+
/** Restore a saved unit offset (deferred so elements can be measured at offset 0). */
|
|
34333
|
+
}, {
|
|
34334
|
+
key: "_restoreUnitOffset",
|
|
34335
|
+
value: function _restoreUnitOffset(key) {
|
|
34336
|
+
var _this0 = this;
|
|
34337
|
+
var saved;
|
|
34338
|
+
try {
|
|
34339
|
+
saved = JSON.parse(window.localStorage.getItem(key) || 'null');
|
|
34340
|
+
} catch (e) {
|
|
34341
|
+
return;
|
|
34342
|
+
}
|
|
34343
|
+
if (!saved || typeof saved.x !== 'number' || typeof saved.y !== 'number') return;
|
|
34344
|
+
requestAnimationFrame(function () {
|
|
34345
|
+
_this0._unitOffset = {
|
|
34346
|
+
x: 0,
|
|
34347
|
+
y: 0
|
|
34348
|
+
}; // ensure DOM matches before measuring
|
|
34349
|
+
var bases = _this0._unitBaseRects();
|
|
34350
|
+
_this0._unitOffset = _this0._clampUnitOffset(saved.x, saved.y, bases);
|
|
34351
|
+
_this0._applyUnitOffset();
|
|
34352
|
+
});
|
|
34353
|
+
}
|
|
34354
|
+
|
|
34355
|
+
/**
|
|
34356
|
+
* Wire a single handle to drag the whole pill+panel unit (shared offset).
|
|
34357
|
+
* @param {HTMLElement} handle
|
|
34358
|
+
* @param {Object} opts
|
|
34359
|
+
* @param {boolean} opts.persist
|
|
34360
|
+
* @param {string} opts.key localStorage key
|
|
34361
|
+
* @param {string} [opts.restCursor] idle cursor (default 'grab')
|
|
34362
|
+
* @param {string} [opts.excludeSelector] don't start a drag from these (e.g. buttons)
|
|
34363
|
+
* @param {Function} [opts.onMoved] called once after a real drag ends
|
|
34364
|
+
*/
|
|
34365
|
+
}, {
|
|
34366
|
+
key: "_attachUnitDrag",
|
|
34367
|
+
value: function _attachUnitDrag(handle, opts) {
|
|
34368
|
+
var _this1 = this;
|
|
34369
|
+
var persist = opts.persist,
|
|
34370
|
+
key = opts.key,
|
|
34371
|
+
excludeSelector = opts.excludeSelector,
|
|
34372
|
+
onMoved = opts.onMoved;
|
|
34373
|
+
var restCursor = opts.restCursor || 'grab';
|
|
34374
|
+
handle.style.setProperty('touch-action', 'none');
|
|
34375
|
+
handle.style.setProperty('cursor', restCursor);
|
|
34376
|
+
var DRAG_THRESHOLD = 5; // px before a press becomes a drag
|
|
34377
|
+
var startX = 0,
|
|
34378
|
+
startY = 0,
|
|
34379
|
+
baseX = 0,
|
|
34380
|
+
baseY = 0,
|
|
34381
|
+
bases = [];
|
|
34382
|
+
var dragging = false,
|
|
34383
|
+
moved = false;
|
|
34384
|
+
var onMove = function onMove(e) {
|
|
34385
|
+
var dx = e.clientX - startX;
|
|
34386
|
+
var dy = e.clientY - startY;
|
|
34387
|
+
if (!moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
|
|
34388
|
+
moved = true;
|
|
34389
|
+
_this1._unitOffset = _this1._clampUnitOffset(baseX + dx, baseY + dy, bases);
|
|
34390
|
+
_this1._applyUnitOffset();
|
|
34391
|
+
};
|
|
34392
|
+
var _onUp = function onUp(e) {
|
|
34393
|
+
window.removeEventListener('pointermove', onMove);
|
|
34394
|
+
window.removeEventListener('pointerup', _onUp);
|
|
34395
|
+
handle.style.setProperty('cursor', restCursor);
|
|
34396
|
+
try {
|
|
34397
|
+
handle.releasePointerCapture(e.pointerId);
|
|
34398
|
+
} catch (err) {/* not captured */}
|
|
34399
|
+
dragging = false;
|
|
34400
|
+
if (moved) {
|
|
34401
|
+
if (typeof onMoved === 'function') onMoved();
|
|
34402
|
+
if (persist && key) {
|
|
34403
|
+
try {
|
|
34404
|
+
window.localStorage.setItem(key, JSON.stringify(_this1._unitOffset));
|
|
34405
|
+
} catch (err) {/* unavailable */}
|
|
34406
|
+
}
|
|
34407
|
+
}
|
|
34408
|
+
};
|
|
34409
|
+
var onDown = function onDown(e) {
|
|
34410
|
+
if (e.button != null && e.button !== 0) return; // primary / touch / pen only
|
|
34411
|
+
if (dragging) return;
|
|
34412
|
+
if (excludeSelector && e.target && e.target.closest && e.target.closest(excludeSelector)) return;
|
|
34413
|
+
dragging = true;
|
|
34414
|
+
moved = false;
|
|
34415
|
+
var o = _this1._unitOffset || (_this1._unitOffset = {
|
|
34416
|
+
x: 0,
|
|
34417
|
+
y: 0
|
|
34418
|
+
});
|
|
34419
|
+
startX = e.clientX;
|
|
34420
|
+
startY = e.clientY;
|
|
34421
|
+
baseX = o.x;
|
|
34422
|
+
baseY = o.y;
|
|
34423
|
+
bases = _this1._unitBaseRects();
|
|
34424
|
+
handle.style.setProperty('cursor', 'grabbing');
|
|
34425
|
+
try {
|
|
34426
|
+
handle.setPointerCapture(e.pointerId);
|
|
34427
|
+
} catch (err) {/* unsupported */}
|
|
34428
|
+
window.addEventListener('pointermove', onMove);
|
|
34429
|
+
window.addEventListener('pointerup', _onUp);
|
|
34430
|
+
};
|
|
34431
|
+
handle.addEventListener('pointerdown', onDown);
|
|
34432
|
+
}
|
|
34433
|
+
|
|
34434
|
+
/**
|
|
34435
|
+
* Make the launcher pill / mobile FAB AND the open chat panel draggable as one
|
|
34436
|
+
* unit — dragging any of them moves both, so they never split apart. Pill/FAB
|
|
34437
|
+
* drags suppress the trailing click (so the panel doesn't toggle); panel header
|
|
34438
|
+
* bars (.ttp-header / .ttp-call-topbar / .text-interface-top-bar) are drag
|
|
34439
|
+
* handles too, with their interactive controls (e.g. close) excluded.
|
|
34440
|
+
*/
|
|
34441
|
+
}, {
|
|
34442
|
+
key: "setupDraggableWidget",
|
|
34443
|
+
value: function setupDraggableWidget() {
|
|
34444
|
+
var _this$config$position6,
|
|
34445
|
+
_this10 = this;
|
|
34446
|
+
var root = this.shadowRoot;
|
|
34447
|
+
if (!root) return;
|
|
34448
|
+
var container = root.getElementById('text-chat-button-container');
|
|
34449
|
+
var panel = root.getElementById('text-chat-panel');
|
|
34450
|
+
if (!container && !panel) return;
|
|
34451
|
+
this._unitOffset = this._unitOffset || {
|
|
34452
|
+
x: 0,
|
|
34453
|
+
y: 0
|
|
34454
|
+
};
|
|
34455
|
+
var persist = ((_this$config$position6 = this.config.position) === null || _this$config$position6 === void 0 ? void 0 : _this$config$position6.draggablePersist) !== false;
|
|
34456
|
+
var key = this._dragStorageKey('unit');
|
|
34457
|
+
if (persist) this._restoreUnitOffset(key);
|
|
34458
|
+
|
|
34459
|
+
// Launcher handles: pill + mobile FAB (suppress the click after a drag).
|
|
34460
|
+
[root.getElementById('text-chat-button'), root.querySelector('.ttp-mobile-fab')].filter(Boolean).forEach(function (h) {
|
|
34461
|
+
return _this10._attachUnitDrag(h, {
|
|
34462
|
+
persist: persist,
|
|
34463
|
+
key: key,
|
|
34464
|
+
restCursor: 'grab',
|
|
34465
|
+
onMoved: function onMoved() {
|
|
34466
|
+
_this10._suppressLauncherClick = true;
|
|
34467
|
+
setTimeout(function () {
|
|
34468
|
+
_this10._suppressLauncherClick = false;
|
|
34469
|
+
}, 0);
|
|
34470
|
+
}
|
|
34471
|
+
});
|
|
34472
|
+
});
|
|
34473
|
+
|
|
34474
|
+
// Panel handles: header bars across voice idle / active call / text views.
|
|
34475
|
+
if (panel) {
|
|
34476
|
+
['.ttp-header', '.ttp-call-topbar', '.text-interface-top-bar'].map(function (sel) {
|
|
34477
|
+
return panel.querySelector(sel);
|
|
34478
|
+
}).filter(Boolean).forEach(function (h) {
|
|
34479
|
+
return _this10._attachUnitDrag(h, {
|
|
34480
|
+
persist: persist,
|
|
34481
|
+
key: key,
|
|
34482
|
+
restCursor: 'move',
|
|
34483
|
+
excludeSelector: 'button, a, input, textarea, select, [contenteditable]'
|
|
34484
|
+
});
|
|
34485
|
+
});
|
|
34486
|
+
}
|
|
34487
|
+
|
|
34488
|
+
// Re-apply any in-memory offset to freshly-rendered elements (re-render).
|
|
34489
|
+
this._applyUnitOffset();
|
|
34490
|
+
this._bindDragResize();
|
|
34491
|
+
}
|
|
34492
|
+
|
|
34493
|
+
/**
|
|
34494
|
+
* Make the desktop minimized voice strip (EcommerceVoiceStrip) draggable. The
|
|
34495
|
+
* strip lives outside the shadow DOM and owns its own drag logic; we just hand
|
|
34496
|
+
* it a persistence key (so it remembers its spot independently of the unit).
|
|
34497
|
+
*/
|
|
34498
|
+
}, {
|
|
34499
|
+
key: "setupDraggableStrip",
|
|
34500
|
+
value: function setupDraggableStrip() {
|
|
34501
|
+
var _this$config$position7;
|
|
34502
|
+
var strip = this._ecommerceVoiceStrip;
|
|
34503
|
+
if (!strip || typeof strip.enableDrag !== 'function') return;
|
|
34504
|
+
strip.enableDrag({
|
|
34505
|
+
persist: ((_this$config$position7 = this.config.position) === null || _this$config$position7 === void 0 ? void 0 : _this$config$position7.draggablePersist) !== false,
|
|
34506
|
+
storageKey: this._dragStorageKey('strip')
|
|
34507
|
+
});
|
|
34508
|
+
}
|
|
34509
|
+
|
|
34510
|
+
/** Bind a single resize listener that re-clamps every dragged surface. */
|
|
34511
|
+
}, {
|
|
34512
|
+
key: "_bindDragResize",
|
|
34513
|
+
value: function _bindDragResize() {
|
|
34514
|
+
var _this11 = this;
|
|
34515
|
+
if (this._dragResizeBound) return;
|
|
34516
|
+
this._dragResizeBound = true;
|
|
34517
|
+
window.addEventListener('resize', function () {
|
|
34518
|
+
var _this11$_ecommerceVoi, _this11$_ecommerceVoi2;
|
|
34519
|
+
_this11._reclampUnit();
|
|
34520
|
+
(_this11$_ecommerceVoi = _this11._ecommerceVoiceStrip) === null || _this11$_ecommerceVoi === void 0 || (_this11$_ecommerceVoi2 = _this11$_ecommerceVoi.reclampDrag) === null || _this11$_ecommerceVoi2 === void 0 || _this11$_ecommerceVoi2.call(_this11$_ecommerceVoi);
|
|
34521
|
+
});
|
|
34522
|
+
}
|
|
33634
34523
|
}, {
|
|
33635
34524
|
key: "startNewChat",
|
|
33636
34525
|
value: function startNewChat() {
|
|
@@ -33677,9 +34566,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33677
34566
|
}, {
|
|
33678
34567
|
key: "_isDomainErrorVisible",
|
|
33679
34568
|
value: function _isDomainErrorVisible() {
|
|
33680
|
-
var _this$
|
|
33681
|
-
if ((_this$
|
|
33682
|
-
var idleState = (_this$
|
|
34569
|
+
var _this$voiceInterface4, _this$voiceInterface5, _idleState$dataset;
|
|
34570
|
+
if ((_this$voiceInterface4 = this.voiceInterface) !== null && _this$voiceInterface4 !== void 0 && _this$voiceInterface4.isShowingDomainError) return true;
|
|
34571
|
+
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
34572
|
return idleState && ((_idleState$dataset = idleState.dataset) === null || _idleState$dataset === void 0 ? void 0 : _idleState$dataset.domainError) === 'true';
|
|
33684
34573
|
}
|
|
33685
34574
|
}, {
|
|
@@ -33707,7 +34596,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33707
34596
|
}, {
|
|
33708
34597
|
key: "_openMobileCallTextLanding",
|
|
33709
34598
|
value: function _openMobileCallTextLanding() {
|
|
33710
|
-
var
|
|
34599
|
+
var _this12 = this;
|
|
33711
34600
|
if (!this.shadowRoot || window.innerWidth > 768) return;
|
|
33712
34601
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33713
34602
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33718,30 +34607,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33718
34607
|
// "Back" button: composedPath includes the panel but not #ttpMobileLanding, so it treated
|
|
33719
34608
|
// the click as "outside" and closed the landing immediately (user only saw the FAB again).
|
|
33720
34609
|
var open = function open() {
|
|
33721
|
-
if (!
|
|
33722
|
-
var panel =
|
|
34610
|
+
if (!_this12.shadowRoot || window.innerWidth > 768) return;
|
|
34611
|
+
var panel = _this12.shadowRoot.getElementById('text-chat-panel');
|
|
33723
34612
|
if (panel) {
|
|
33724
34613
|
panel.classList.remove('open');
|
|
33725
|
-
|
|
34614
|
+
_this12.isOpen = false;
|
|
33726
34615
|
}
|
|
33727
|
-
if (
|
|
33728
|
-
|
|
34616
|
+
if (_this12.config.promptAnimation.hideAfterClick) {
|
|
34617
|
+
_this12.hidePrompt();
|
|
33729
34618
|
}
|
|
33730
|
-
var errorBanner =
|
|
34619
|
+
var errorBanner = _this12.shadowRoot.getElementById('ttpMobileLandingError');
|
|
33731
34620
|
if (errorBanner) errorBanner.style.display = 'none';
|
|
33732
|
-
var fab =
|
|
33733
|
-
var landing =
|
|
34621
|
+
var fab = _this12.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
34622
|
+
var landing = _this12.shadowRoot.getElementById('ttpMobileLanding');
|
|
33734
34623
|
if (!fab || !landing) return;
|
|
33735
34624
|
fab.style.display = 'none';
|
|
33736
34625
|
landing.classList.add('active');
|
|
33737
|
-
|
|
34626
|
+
_this12.isMobileLandingOpen = true;
|
|
33738
34627
|
};
|
|
33739
34628
|
queueMicrotask(open);
|
|
33740
34629
|
}
|
|
33741
34630
|
}, {
|
|
33742
34631
|
key: "setupMobileWidgetEvents",
|
|
33743
34632
|
value: function setupMobileWidgetEvents() {
|
|
33744
|
-
var
|
|
34633
|
+
var _this13 = this;
|
|
33745
34634
|
if (!this.shadowRoot) return;
|
|
33746
34635
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33747
34636
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33749,10 +34638,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33749
34638
|
var closeMobileLanding = function closeMobileLanding() {
|
|
33750
34639
|
mobileLanding.classList.remove('active');
|
|
33751
34640
|
mobileFab.style.display = '';
|
|
33752
|
-
|
|
34641
|
+
_this13.isMobileLandingOpen = false;
|
|
33753
34642
|
};
|
|
33754
34643
|
mobileFab.onclick = function () {
|
|
33755
|
-
|
|
34644
|
+
// A drag just ended — don't open the landing on the trailing click.
|
|
34645
|
+
if (_this13._suppressLauncherClick) return;
|
|
34646
|
+
_this13._openMobileCallTextLanding();
|
|
33756
34647
|
};
|
|
33757
34648
|
var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
|
|
33758
34649
|
if (mobileClose) {
|
|
@@ -33762,18 +34653,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33762
34653
|
if (mobileCallBtn) {
|
|
33763
34654
|
mobileCallBtn.onclick = function () {
|
|
33764
34655
|
closeMobileLanding();
|
|
33765
|
-
var panel =
|
|
34656
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33766
34657
|
if (panel) {
|
|
33767
34658
|
panel.style.removeProperty('display');
|
|
33768
34659
|
panel.classList.add('open');
|
|
33769
|
-
|
|
34660
|
+
_this13.isOpen = true;
|
|
33770
34661
|
}
|
|
33771
34662
|
mobileFab.style.display = 'none';
|
|
33772
|
-
|
|
34663
|
+
_this13.showVoice();
|
|
33773
34664
|
// Landing already chose "Voice call" — start the call (mic permission / pre-prompt) instead of
|
|
33774
34665
|
// leaving users on a second "Start Call" tap that feels broken.
|
|
33775
34666
|
queueMicrotask(function () {
|
|
33776
|
-
|
|
34667
|
+
_this13.startVoiceCall().catch(function (err) {
|
|
33777
34668
|
console.error('[TTPChatWidget] Mobile landing voice start failed:', err);
|
|
33778
34669
|
});
|
|
33779
34670
|
});
|
|
@@ -33783,20 +34674,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33783
34674
|
if (mobileChatBtn) {
|
|
33784
34675
|
mobileChatBtn.onclick = function () {
|
|
33785
34676
|
closeMobileLanding();
|
|
33786
|
-
var panel =
|
|
34677
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33787
34678
|
if (panel) {
|
|
33788
34679
|
panel.style.removeProperty('display');
|
|
33789
34680
|
panel.classList.add('open');
|
|
33790
|
-
|
|
34681
|
+
_this13.isOpen = true;
|
|
33791
34682
|
}
|
|
33792
34683
|
mobileFab.style.display = 'none';
|
|
33793
|
-
|
|
34684
|
+
_this13.showText();
|
|
33794
34685
|
};
|
|
33795
34686
|
}
|
|
33796
34687
|
|
|
33797
34688
|
// Close mobile landing on outside click
|
|
33798
34689
|
document.addEventListener('click', function (e) {
|
|
33799
|
-
if (!
|
|
34690
|
+
if (!_this13.isMobileLandingOpen) return;
|
|
33800
34691
|
var path = e.composedPath();
|
|
33801
34692
|
if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
|
|
33802
34693
|
closeMobileLanding();
|
|
@@ -33805,7 +34696,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33805
34696
|
|
|
33806
34697
|
// Close mobile landing on Escape
|
|
33807
34698
|
document.addEventListener('keydown', function (e) {
|
|
33808
|
-
if (e.key === 'Escape' &&
|
|
34699
|
+
if (e.key === 'Escape' && _this13.isMobileLandingOpen) {
|
|
33809
34700
|
closeMobileLanding();
|
|
33810
34701
|
}
|
|
33811
34702
|
});
|
|
@@ -33821,19 +34712,19 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33821
34712
|
_prevIsMobile = nowMobile;
|
|
33822
34713
|
if (nowMobile) {
|
|
33823
34714
|
// Switched desktop → mobile: close desktop panel so only mobile FAB shows
|
|
33824
|
-
if (
|
|
33825
|
-
var
|
|
33826
|
-
var panel = (
|
|
34715
|
+
if (_this13.isOpen) {
|
|
34716
|
+
var _this13$shadowRoot, _this13$shadowRoot2;
|
|
34717
|
+
var panel = (_this13$shadowRoot = _this13.shadowRoot) === null || _this13$shadowRoot === void 0 ? void 0 : _this13$shadowRoot.getElementById('text-chat-panel');
|
|
33827
34718
|
if (panel) {
|
|
33828
34719
|
panel.classList.remove('open');
|
|
33829
|
-
|
|
34720
|
+
_this13.isOpen = false;
|
|
33830
34721
|
}
|
|
33831
|
-
var pill = (
|
|
34722
|
+
var pill = (_this13$shadowRoot2 = _this13.shadowRoot) === null || _this13$shadowRoot2 === void 0 ? void 0 : _this13$shadowRoot2.getElementById('text-chat-button');
|
|
33832
34723
|
if (pill) pill.classList.remove('open');
|
|
33833
34724
|
}
|
|
33834
34725
|
} else {
|
|
33835
34726
|
// Switched mobile → desktop: close mobile landing/FAB so only desktop pill shows
|
|
33836
|
-
if (
|
|
34727
|
+
if (_this13.isMobileLandingOpen) {
|
|
33837
34728
|
closeMobileLanding();
|
|
33838
34729
|
}
|
|
33839
34730
|
// Ensure mobile FAB is reset to CSS-controlled state (media query hides it on desktop)
|
|
@@ -33845,10 +34736,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33845
34736
|
}, {
|
|
33846
34737
|
key: "setupKeyboardNavigation",
|
|
33847
34738
|
value: function setupKeyboardNavigation() {
|
|
33848
|
-
var
|
|
34739
|
+
var _this14 = this;
|
|
33849
34740
|
document.addEventListener('keydown', function (e) {
|
|
33850
|
-
if (e.key === 'Escape' &&
|
|
33851
|
-
|
|
34741
|
+
if (e.key === 'Escape' && _this14.isOpen) {
|
|
34742
|
+
_this14.togglePanel();
|
|
33852
34743
|
}
|
|
33853
34744
|
});
|
|
33854
34745
|
}
|
|
@@ -33859,7 +34750,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33859
34750
|
}, {
|
|
33860
34751
|
key: "setupPromptAnimation",
|
|
33861
34752
|
value: function setupPromptAnimation() {
|
|
33862
|
-
var
|
|
34753
|
+
var _this15 = this;
|
|
33863
34754
|
if (!this.shadowRoot) return;
|
|
33864
34755
|
var promptConfig = this.config.promptAnimation || {};
|
|
33865
34756
|
// Default to disabled if not specified (enabled === true means explicitly enabled)
|
|
@@ -33889,7 +34780,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33889
34780
|
// Auto-hide after configured seconds (only if widget is closed)
|
|
33890
34781
|
if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
|
|
33891
34782
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
33892
|
-
|
|
34783
|
+
_this15.hidePrompt();
|
|
33893
34784
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
33894
34785
|
}
|
|
33895
34786
|
|
|
@@ -33901,7 +34792,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33901
34792
|
// Wrap the callback to also hide pulse rings
|
|
33902
34793
|
this.config.onConversationStart = function () {
|
|
33903
34794
|
// Hide pulse rings when call starts
|
|
33904
|
-
var pulseRings =
|
|
34795
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33905
34796
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33906
34797
|
|
|
33907
34798
|
// Call original callback if it exists
|
|
@@ -33913,7 +34804,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33913
34804
|
// Also listen to recordingStarted event from SDK if available
|
|
33914
34805
|
if (this.voiceInterface.sdk.voiceSDK) {
|
|
33915
34806
|
this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
|
|
33916
|
-
var pulseRings =
|
|
34807
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33917
34808
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33918
34809
|
});
|
|
33919
34810
|
}
|
|
@@ -33961,7 +34852,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33961
34852
|
}, {
|
|
33962
34853
|
key: "showPrompt",
|
|
33963
34854
|
value: function showPrompt() {
|
|
33964
|
-
var
|
|
34855
|
+
var _this16 = this;
|
|
33965
34856
|
if (!this.shadowRoot) return;
|
|
33966
34857
|
var promptConfig = this.config.promptAnimation || {};
|
|
33967
34858
|
// Default to enabled if not specified
|
|
@@ -33981,8 +34872,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33981
34872
|
// Function to actually show the elements
|
|
33982
34873
|
var doShow = function doShow() {
|
|
33983
34874
|
// Show prompt bubble (check both shadow root and document for compatibility)
|
|
33984
|
-
var promptBubble =
|
|
33985
|
-
if (!promptBubble &&
|
|
34875
|
+
var promptBubble = _this16.shadowRoot.getElementById('prompt-bubble');
|
|
34876
|
+
if (!promptBubble && _this16.shadowRoot !== document) {
|
|
33986
34877
|
promptBubble = document.getElementById('prompt-bubble');
|
|
33987
34878
|
}
|
|
33988
34879
|
if (promptBubble) {
|
|
@@ -33996,8 +34887,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33996
34887
|
|
|
33997
34888
|
// Show pulse rings if enabled
|
|
33998
34889
|
if (promptConfig.showPulseRings !== false) {
|
|
33999
|
-
var _pulseRings =
|
|
34000
|
-
if (!_pulseRings &&
|
|
34890
|
+
var _pulseRings = _this16.shadowRoot.getElementById('prompt-pulse-rings');
|
|
34891
|
+
if (!_pulseRings && _this16.shadowRoot !== document) {
|
|
34001
34892
|
_pulseRings = document.getElementById('prompt-pulse-rings');
|
|
34002
34893
|
}
|
|
34003
34894
|
if (_pulseRings) {
|
|
@@ -34034,7 +34925,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34034
34925
|
}
|
|
34035
34926
|
// Start new timer
|
|
34036
34927
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
34037
|
-
|
|
34928
|
+
_this16.hidePrompt();
|
|
34038
34929
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
34039
34930
|
}
|
|
34040
34931
|
}
|
|
@@ -34050,14 +34941,23 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34050
34941
|
}, {
|
|
34051
34942
|
key: "_doTogglePanel",
|
|
34052
34943
|
value: function _doTogglePanel() {
|
|
34053
|
-
var
|
|
34944
|
+
var _this17 = this;
|
|
34054
34945
|
if (!this.shadowRoot) return;
|
|
34055
34946
|
this.isOpen = !this.isOpen;
|
|
34056
34947
|
var panel = this.shadowRoot.getElementById('text-chat-panel');
|
|
34057
34948
|
if (panel) {
|
|
34058
34949
|
panel.classList.toggle('open');
|
|
34059
34950
|
if (this.isOpen) {
|
|
34951
|
+
var _this$config$position8;
|
|
34060
34952
|
panel.style.removeProperty('display');
|
|
34953
|
+
// The panel joins the dragged unit when it opens; re-clamp now that it
|
|
34954
|
+
// has real dimensions (it was hidden/zero-size while closed).
|
|
34955
|
+
if ((_this$config$position8 = this.config.position) !== null && _this$config$position8 !== void 0 && _this$config$position8.draggable) {
|
|
34956
|
+
this._applyUnitOffset();
|
|
34957
|
+
requestAnimationFrame(function () {
|
|
34958
|
+
return _this17._reclampUnit();
|
|
34959
|
+
});
|
|
34960
|
+
}
|
|
34061
34961
|
}
|
|
34062
34962
|
}
|
|
34063
34963
|
|
|
@@ -34072,7 +34972,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34072
34972
|
// Panel is opening - hide prompt
|
|
34073
34973
|
this.hidePrompt();
|
|
34074
34974
|
setTimeout(function () {
|
|
34075
|
-
var input =
|
|
34975
|
+
var input = _this17.shadowRoot.getElementById('messageInput');
|
|
34076
34976
|
if (input) input.focus();
|
|
34077
34977
|
}, 100);
|
|
34078
34978
|
} else {
|
|
@@ -34084,13 +34984,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34084
34984
|
// Panel is closing - show prompt (if enabled)
|
|
34085
34985
|
this.showPrompt();
|
|
34086
34986
|
setTimeout(function () {
|
|
34087
|
-
var
|
|
34088
|
-
var promptBubble =
|
|
34987
|
+
var _this17$config$prompt;
|
|
34988
|
+
var promptBubble = _this17.shadowRoot.getElementById('prompt-bubble');
|
|
34089
34989
|
if (promptBubble && promptBubble.style.display === 'none') {
|
|
34090
34990
|
promptBubble.style.display = 'block';
|
|
34091
34991
|
}
|
|
34092
|
-
var pulseRings =
|
|
34093
|
-
if (pulseRings && ((
|
|
34992
|
+
var pulseRings = _this17.shadowRoot.getElementById('prompt-pulse-rings');
|
|
34993
|
+
if (pulseRings && ((_this17$config$prompt = _this17.config.promptAnimation) === null || _this17$config$prompt === void 0 ? void 0 : _this17$config$prompt.showPulseRings) !== false) {
|
|
34094
34994
|
if (pulseRings.style.display === 'none') {
|
|
34095
34995
|
pulseRings.style.display = 'block';
|
|
34096
34996
|
}
|
|
@@ -34282,8 +35182,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34282
35182
|
}, {
|
|
34283
35183
|
key: "showBackButtonWarning",
|
|
34284
35184
|
value: function showBackButtonWarning() {
|
|
34285
|
-
var _this$
|
|
34286
|
-
if (!((_this$
|
|
35185
|
+
var _this$voiceInterface6, _this$voiceInterface$;
|
|
35186
|
+
if (!((_this$voiceInterface6 = this.voiceInterface) !== null && _this$voiceInterface6 !== void 0 && _this$voiceInterface6.isActive)) return;
|
|
34287
35187
|
|
|
34288
35188
|
// Show warning message in the voice interface
|
|
34289
35189
|
if ((_this$voiceInterface$ = this.voiceInterface.desktop) !== null && _this$voiceInterface$ !== void 0 && _this$voiceInterface$.showBackButtonWarning) {
|
|
@@ -34364,7 +35264,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34364
35264
|
_this$config$voice0,
|
|
34365
35265
|
_this$config$voice1,
|
|
34366
35266
|
_this$config$voice10,
|
|
34367
|
-
|
|
35267
|
+
_this18 = this;
|
|
34368
35268
|
// Deep merge nested objects
|
|
34369
35269
|
var mergedConfig = _objectSpread({}, this.config);
|
|
34370
35270
|
|
|
@@ -34582,20 +35482,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34582
35482
|
outputBitDepth: ((_this$config$voice10 = this.config.voice) === null || _this$config$voice10 === void 0 ? void 0 : _this$config$voice10.outputBitDepth) || 16,
|
|
34583
35483
|
desktopMinimizedEcommerceStripUi: desktopMinimizedEcommerceStripUi,
|
|
34584
35484
|
onDesktopMinimizedStripCallStart: desktopMinimizedEcommerceStripUi ? function () {
|
|
34585
|
-
var
|
|
34586
|
-
(
|
|
34587
|
-
if (
|
|
34588
|
-
|
|
34589
|
-
|
|
35485
|
+
var _this18$_ecommerceVoi;
|
|
35486
|
+
(_this18$_ecommerceVoi = _this18._ecommerceVoiceStrip) === null || _this18$_ecommerceVoi === void 0 || _this18$_ecommerceVoi.show();
|
|
35487
|
+
if (_this18.isOpen) _this18.minimize();
|
|
35488
|
+
_this18._setPanelFooterVisible(false);
|
|
35489
|
+
_this18._setEcommerceStripLauncherVisible(false);
|
|
34590
35490
|
} : undefined,
|
|
34591
35491
|
onDesktopMinimizedStripLauncherRestore: desktopMinimizedEcommerceStripUi ? function () {
|
|
34592
|
-
return
|
|
35492
|
+
return _this18._restoreDesktopEcommerceStripChrome();
|
|
34593
35493
|
} : undefined,
|
|
34594
35494
|
// Pass event callbacks to voice interface (forward only; panel is not auto-minimized on call start)
|
|
34595
35495
|
onConversationStart: function onConversationStart() {
|
|
34596
|
-
if (typeof
|
|
34597
|
-
var
|
|
34598
|
-
(
|
|
35496
|
+
if (typeof _this18.config.onConversationStart === 'function') {
|
|
35497
|
+
var _this18$config;
|
|
35498
|
+
(_this18$config = _this18.config).onConversationStart.apply(_this18$config, arguments);
|
|
34599
35499
|
}
|
|
34600
35500
|
},
|
|
34601
35501
|
onConversationEnd: this.config.onConversationEnd,
|
|
@@ -34604,48 +35504,48 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34604
35504
|
onAudioStoppedPlaying: this.config.onAudioStoppedPlaying,
|
|
34605
35505
|
onSubtitleDisplay: this.config.onSubtitleDisplay,
|
|
34606
35506
|
onCallEnd: function onCallEnd() {
|
|
34607
|
-
var
|
|
34608
|
-
if (
|
|
34609
|
-
var widgetMode = ((
|
|
35507
|
+
var _this18$config$behavi;
|
|
35508
|
+
if (_this18._isDomainErrorVisible()) return;
|
|
35509
|
+
var widgetMode = ((_this18$config$behavi = _this18.config.behavior) === null || _this18$config$behavi === void 0 ? void 0 : _this18$config$behavi.mode) || 'unified';
|
|
34610
35510
|
if (widgetMode === 'unified') {
|
|
34611
35511
|
if (window.innerWidth <= 768) {
|
|
34612
|
-
var
|
|
34613
|
-
var panel = (
|
|
35512
|
+
var _this18$shadowRoot, _this18$shadowRoot2;
|
|
35513
|
+
var panel = (_this18$shadowRoot = _this18.shadowRoot) === null || _this18$shadowRoot === void 0 ? void 0 : _this18$shadowRoot.getElementById('text-chat-panel');
|
|
34614
35514
|
if (panel) {
|
|
34615
35515
|
panel.classList.remove('open');
|
|
34616
|
-
|
|
35516
|
+
_this18.isOpen = false;
|
|
34617
35517
|
}
|
|
34618
|
-
var fab = (
|
|
35518
|
+
var fab = (_this18$shadowRoot2 = _this18.shadowRoot) === null || _this18$shadowRoot2 === void 0 ? void 0 : _this18$shadowRoot2.querySelector('.ttp-mobile-fab');
|
|
34619
35519
|
if (fab) fab.style.display = '';
|
|
34620
35520
|
}
|
|
34621
|
-
|
|
35521
|
+
_this18.showLanding();
|
|
34622
35522
|
}
|
|
34623
35523
|
},
|
|
34624
35524
|
onShowVoice: function onShowVoice() {
|
|
34625
|
-
|
|
35525
|
+
_this18.showVoice();
|
|
34626
35526
|
},
|
|
34627
35527
|
onShowLanding: function onShowLanding() {
|
|
34628
|
-
|
|
35528
|
+
_this18.showLanding();
|
|
34629
35529
|
},
|
|
34630
35530
|
onDisclaimerDeclined: function onDisclaimerDeclined() {
|
|
34631
|
-
var
|
|
34632
|
-
if (
|
|
34633
|
-
var widgetMode = ((
|
|
35531
|
+
var _this18$config$behavi2;
|
|
35532
|
+
if (_this18._isDomainErrorVisible()) return;
|
|
35533
|
+
var widgetMode = ((_this18$config$behavi2 = _this18.config.behavior) === null || _this18$config$behavi2 === void 0 ? void 0 : _this18$config$behavi2.mode) || 'unified';
|
|
34634
35534
|
if (widgetMode === 'voice-only') {
|
|
34635
|
-
|
|
35535
|
+
_this18.showVoice();
|
|
34636
35536
|
return;
|
|
34637
35537
|
}
|
|
34638
35538
|
if (widgetMode !== 'unified') return;
|
|
34639
35539
|
if (window.innerWidth <= 768) {
|
|
34640
|
-
var
|
|
34641
|
-
var panel = (
|
|
35540
|
+
var _this18$shadowRoot3;
|
|
35541
|
+
var panel = (_this18$shadowRoot3 = _this18.shadowRoot) === null || _this18$shadowRoot3 === void 0 ? void 0 : _this18$shadowRoot3.getElementById('text-chat-panel');
|
|
34642
35542
|
if (panel) {
|
|
34643
35543
|
panel.classList.remove('open');
|
|
34644
|
-
|
|
35544
|
+
_this18.isOpen = false;
|
|
34645
35545
|
}
|
|
34646
|
-
|
|
35546
|
+
_this18._openMobileCallTextLanding();
|
|
34647
35547
|
} else {
|
|
34648
|
-
|
|
35548
|
+
_this18.showLanding();
|
|
34649
35549
|
}
|
|
34650
35550
|
},
|
|
34651
35551
|
direction: this.getEffectiveTextDirection()
|
|
@@ -34692,8 +35592,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34692
35592
|
}, {
|
|
34693
35593
|
key: "_initEcommerceVoiceStrip",
|
|
34694
35594
|
value: function _initEcommerceVoiceStrip() {
|
|
34695
|
-
var
|
|
34696
|
-
_this$
|
|
35595
|
+
var _this19 = this,
|
|
35596
|
+
_this$config$position9,
|
|
35597
|
+
_this$voiceInterface7;
|
|
34697
35598
|
var flavor = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
34698
35599
|
if (window.innerWidth <= 768) return;
|
|
34699
35600
|
if (!flavor || flavor.callView !== 'minimized') return;
|
|
@@ -34714,31 +35615,34 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34714
35615
|
endCallButtonColor: v.endCallButtonColor || '#ef4444'
|
|
34715
35616
|
},
|
|
34716
35617
|
getVoiceUiState: function getVoiceUiState() {
|
|
34717
|
-
var
|
|
35618
|
+
var _this19$voiceInterfac, _this19$voiceInterfac2, _this19$voiceInterfac3;
|
|
34718
35619
|
return {
|
|
34719
|
-
isMicMuted: !!((
|
|
34720
|
-
isPaused: !!((
|
|
34721
|
-
isSpeakerMuted: !!((
|
|
35620
|
+
isMicMuted: !!((_this19$voiceInterfac = _this19.voiceInterface) !== null && _this19$voiceInterfac !== void 0 && _this19$voiceInterfac.isMicMuted),
|
|
35621
|
+
isPaused: !!((_this19$voiceInterfac2 = _this19.voiceInterface) !== null && _this19$voiceInterfac2 !== void 0 && _this19$voiceInterfac2.isPaused),
|
|
35622
|
+
isSpeakerMuted: !!((_this19$voiceInterfac3 = _this19.voiceInterface) !== null && _this19$voiceInterfac3 !== void 0 && _this19$voiceInterfac3.isSpeakerMuted)
|
|
34722
35623
|
};
|
|
34723
35624
|
},
|
|
35625
|
+
onAbout: function onAbout() {
|
|
35626
|
+
return _this19._openAboutModal();
|
|
35627
|
+
},
|
|
34724
35628
|
onHangup: function onHangup() {
|
|
34725
|
-
if (
|
|
35629
|
+
if (_this19.voiceInterface) _this19.voiceInterface.endVoiceCall();
|
|
34726
35630
|
},
|
|
34727
35631
|
onToggleMute: function onToggleMute() {
|
|
34728
|
-
if (
|
|
35632
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleMute();
|
|
34729
35633
|
strip.syncFromVoice();
|
|
34730
35634
|
},
|
|
34731
35635
|
onTogglePause: function onTogglePause() {
|
|
34732
|
-
if (
|
|
35636
|
+
if (_this19.voiceInterface) _this19.voiceInterface.togglePause();
|
|
34733
35637
|
strip.syncFromVoice();
|
|
34734
35638
|
},
|
|
34735
35639
|
onToggleSpeaker: function onToggleSpeaker() {
|
|
34736
|
-
if (
|
|
35640
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleSpeaker();
|
|
34737
35641
|
strip.syncFromVoice();
|
|
34738
35642
|
},
|
|
34739
35643
|
onSendText: function onSendText(text) {
|
|
34740
|
-
var
|
|
34741
|
-
var voiceSDK = (
|
|
35644
|
+
var _this19$voiceInterfac4;
|
|
35645
|
+
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
35646
|
if (voiceSDK && typeof voiceSDK.sendMessage === 'function') {
|
|
34743
35647
|
voiceSDK.sendMessage({
|
|
34744
35648
|
t: 'text_inject',
|
|
@@ -34749,8 +35653,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34749
35653
|
});
|
|
34750
35654
|
this._ecommerceVoiceStrip = strip;
|
|
34751
35655
|
|
|
35656
|
+
// Make the strip draggable too when position.draggable is enabled.
|
|
35657
|
+
if ((_this$config$position9 = this.config.position) !== null && _this$config$position9 !== void 0 && _this$config$position9.draggable) {
|
|
35658
|
+
this.setupDraggableStrip();
|
|
35659
|
+
}
|
|
35660
|
+
|
|
34752
35661
|
// Show strip when conversation starts
|
|
34753
|
-
var agentSDK = (_this$
|
|
35662
|
+
var agentSDK = (_this$voiceInterface7 = this.voiceInterface) === null || _this$voiceInterface7 === void 0 ? void 0 : _this$voiceInterface7.sdk;
|
|
34754
35663
|
if (agentSDK) {
|
|
34755
35664
|
var origConvStart = agentSDK.onConversationStart;
|
|
34756
35665
|
agentSDK.onConversationStart = function () {
|
|
@@ -34788,7 +35697,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34788
35697
|
var _this$voiceInterface$2;
|
|
34789
35698
|
var origOnCallEnd = this.voiceInterface.config.onCallEnd;
|
|
34790
35699
|
this.voiceInterface.config.onCallEnd = function () {
|
|
34791
|
-
|
|
35700
|
+
_this19._restoreDesktopEcommerceStripChrome();
|
|
34792
35701
|
if (typeof origOnCallEnd === 'function') origOnCallEnd();
|
|
34793
35702
|
};
|
|
34794
35703
|
|
|
@@ -34912,7 +35821,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34912
35821
|
key: "injectData",
|
|
34913
35822
|
value: (function () {
|
|
34914
35823
|
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
34915
|
-
var _this$
|
|
35824
|
+
var _this$voiceInterface8;
|
|
34916
35825
|
var options,
|
|
34917
35826
|
voiceSDK,
|
|
34918
35827
|
ack,
|
|
@@ -34937,7 +35846,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34937
35846
|
throw new Error('Voice call is not active');
|
|
34938
35847
|
case 2:
|
|
34939
35848
|
// Check if SDK is available
|
|
34940
|
-
voiceSDK = (_this$
|
|
35849
|
+
voiceSDK = (_this$voiceInterface8 = this.voiceInterface) === null || _this$voiceInterface8 === void 0 ? void 0 : _this$voiceInterface8.getVoiceSDK();
|
|
34941
35850
|
if (voiceSDK) {
|
|
34942
35851
|
_context6.n = 3;
|
|
34943
35852
|
break;
|
|
@@ -35202,7 +36111,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35202
36111
|
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
36112
|
var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
|
|
35204
36113
|
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>") : '';
|
|
36114
|
+
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
36115
|
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
36116
|
}
|
|
35208
36117
|
|
|
@@ -35334,7 +36243,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35334
36243
|
|
|
35335
36244
|
// Add !important to display rules when not using Shadow DOM (to override theme CSS)
|
|
35336
36245
|
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 ");
|
|
36246
|
+
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
36247
|
}
|
|
35339
36248
|
|
|
35340
36249
|
/**
|
|
@@ -37412,6 +38321,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37412
38321
|
clearInterval(this.callTimerInterval);
|
|
37413
38322
|
this.callTimerInterval = null;
|
|
37414
38323
|
}
|
|
38324
|
+
this.callStartTime = null;
|
|
37415
38325
|
|
|
37416
38326
|
// Hide active state, show idle state first
|
|
37417
38327
|
activeState = this.shadowRoot.getElementById('voiceActiveState');
|
|
@@ -37580,6 +38490,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37580
38490
|
clearInterval(this.callTimerInterval);
|
|
37581
38491
|
this.callTimerInterval = null;
|
|
37582
38492
|
}
|
|
38493
|
+
// Reset the start time so the next call's timer block (gated on !callStartTime)
|
|
38494
|
+
// actually restarts the interval. Without this, the timer only ever runs for the
|
|
38495
|
+
// first call and stays stuck at 00:00 on every subsequent call.
|
|
38496
|
+
this.callStartTime = null;
|
|
37583
38497
|
|
|
37584
38498
|
// Clean up text inject timeouts and handlers (desktop)
|
|
37585
38499
|
if (this._textInjectTimeout) {
|
|
@@ -40327,6 +41241,21 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40327
41241
|
return this.voiceInterface.getTooltip(key);
|
|
40328
41242
|
}
|
|
40329
41243
|
|
|
41244
|
+
/**
|
|
41245
|
+
* Shared "About" info ("i") button markup. Opens the About dialog
|
|
41246
|
+
* (SDK version + last conversation id) wired by TTPChatWidget.
|
|
41247
|
+
* @param {string} [extraClass] - extra class(es) for positioning per view
|
|
41248
|
+
* @returns {string}
|
|
41249
|
+
*/
|
|
41250
|
+
}, {
|
|
41251
|
+
key: "infoButton",
|
|
41252
|
+
value: function infoButton() {
|
|
41253
|
+
var extraClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
41254
|
+
var cls = extraClass ? "ttp-info-btn ".concat(extraClass) : 'ttp-info-btn';
|
|
41255
|
+
var label = this.t('aboutTitle') || 'About';
|
|
41256
|
+
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>");
|
|
41257
|
+
}
|
|
41258
|
+
|
|
40330
41259
|
/**
|
|
40331
41260
|
* Generate HTML for voice interface.
|
|
40332
41261
|
* Automatically detects mobile vs desktop based on voiceInterface.isMobile
|
|
@@ -40357,7 +41286,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40357
41286
|
var transcriptPlaceholder = this.t('transcriptWillAppear') || '';
|
|
40358
41287
|
var transcriptDir = (0,_rtlText_js__WEBPACK_IMPORTED_MODULE_0__.dirForTranscriptSnippet)(transcriptPlaceholder, this.config);
|
|
40359
41288
|
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>");
|
|
41289
|
+
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
41290
|
}
|
|
40362
41291
|
|
|
40363
41292
|
/**
|
|
@@ -40374,7 +41303,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40374
41303
|
var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
|
|
40375
41304
|
var mobileAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"voice-avatar-img\" />") : '🤖';
|
|
40376
41305
|
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
|
|
41306
|
+
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
41307
|
return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
|
|
40379
41308
|
}).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
41309
|
}
|
|
@@ -41219,7 +42148,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41219
42148
|
"typeMessage": "Type your message...",
|
|
41220
42149
|
"sendMessageAria": "Send message",
|
|
41221
42150
|
"domainNotValidated": "Domain not validated",
|
|
41222
|
-
"domainErrorMessage": "This domain is not whitelisted. Please contact the administrator to whitelist your website URL."
|
|
42151
|
+
"domainErrorMessage": "This domain is not whitelisted. Please contact the administrator to whitelist your website URL.",
|
|
42152
|
+
"aboutTitle": "About",
|
|
42153
|
+
"aboutVersion": "SDK version",
|
|
42154
|
+
"aboutConversationId": "Last conversation ID",
|
|
42155
|
+
"aboutNoConversation": "No conversation yet"
|
|
41223
42156
|
},
|
|
41224
42157
|
"he": {
|
|
41225
42158
|
"landingTitle": "איך תרצה לתקשר?",
|
|
@@ -41252,7 +42185,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41252
42185
|
"typeMessage": "הקלד הודעה...",
|
|
41253
42186
|
"sendMessageAria": "שלח הודעה",
|
|
41254
42187
|
"domainNotValidated": "דומיין לא מאומת",
|
|
41255
|
-
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה."
|
|
42188
|
+
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה.",
|
|
42189
|
+
"aboutTitle": "אודות",
|
|
42190
|
+
"aboutVersion": "גרסת SDK",
|
|
42191
|
+
"aboutConversationId": "מזהה שיחה אחרון",
|
|
42192
|
+
"aboutNoConversation": "אין שיחה עדיין"
|
|
41256
42193
|
},
|
|
41257
42194
|
"ar": {
|
|
41258
42195
|
"landingTitle": "كيف تريد التواصل؟",
|
|
@@ -41285,7 +42222,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41285
42222
|
"typeMessage": "اكتب رسالة...",
|
|
41286
42223
|
"sendMessageAria": "إرسال رسالة",
|
|
41287
42224
|
"domainNotValidated": "النطاق غير معتمد",
|
|
41288
|
-
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة."
|
|
42225
|
+
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة.",
|
|
42226
|
+
"aboutTitle": "حول",
|
|
42227
|
+
"aboutVersion": "إصدار SDK",
|
|
42228
|
+
"aboutConversationId": "معرّف آخر محادثة",
|
|
42229
|
+
"aboutNoConversation": "لا توجد محادثة بعد"
|
|
41289
42230
|
},
|
|
41290
42231
|
"ru": {
|
|
41291
42232
|
"landingTitle": "Как вы хотите общаться?",
|
|
@@ -41318,7 +42259,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41318
42259
|
"typeMessage": "Введите сообщение...",
|
|
41319
42260
|
"sendMessageAria": "Отправить сообщение",
|
|
41320
42261
|
"domainNotValidated": "Домен не проверен",
|
|
41321
|
-
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список."
|
|
42262
|
+
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список.",
|
|
42263
|
+
"aboutTitle": "О приложении",
|
|
42264
|
+
"aboutVersion": "Версия SDK",
|
|
42265
|
+
"aboutConversationId": "ID последнего разговора",
|
|
42266
|
+
"aboutNoConversation": "Разговоров пока нет"
|
|
41322
42267
|
},
|
|
41323
42268
|
"es": {
|
|
41324
42269
|
"landingTitle": "¿Cómo te gustaría comunicarte?",
|
|
@@ -41351,7 +42296,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41351
42296
|
"typeMessage": "Escribe un mensaje...",
|
|
41352
42297
|
"sendMessageAria": "Enviar mensaje",
|
|
41353
42298
|
"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."
|
|
42299
|
+
"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.",
|
|
42300
|
+
"aboutTitle": "Acerca de",
|
|
42301
|
+
"aboutVersion": "Versión del SDK",
|
|
42302
|
+
"aboutConversationId": "ID de última conversación",
|
|
42303
|
+
"aboutNoConversation": "Aún no hay conversación"
|
|
41355
42304
|
},
|
|
41356
42305
|
"fr": {
|
|
41357
42306
|
"landingTitle": "Comment souhaitez-vous communiquer?",
|
|
@@ -41384,7 +42333,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41384
42333
|
"typeMessage": "Tapez votre message...",
|
|
41385
42334
|
"sendMessageAria": "Envoyer un message",
|
|
41386
42335
|
"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."
|
|
42336
|
+
"domainErrorMessage": "Ce domaine n'est pas sur la liste blanche. Veuillez contacter l'administrateur pour ajouter l'URL de votre site Web à la liste.",
|
|
42337
|
+
"aboutTitle": "À propos",
|
|
42338
|
+
"aboutVersion": "Version du SDK",
|
|
42339
|
+
"aboutConversationId": "ID de la dernière conversation",
|
|
42340
|
+
"aboutNoConversation": "Aucune conversation pour l'instant"
|
|
41388
42341
|
},
|
|
41389
42342
|
"de": {
|
|
41390
42343
|
"landingTitle": "Wie möchten Sie kommunizieren?",
|
|
@@ -41417,7 +42370,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41417
42370
|
"typeMessage": "Geben Sie eine Nachricht ein...",
|
|
41418
42371
|
"sendMessageAria": "Nachricht senden",
|
|
41419
42372
|
"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."
|
|
42373
|
+
"domainErrorMessage": "Diese Domain steht nicht auf der Whitelist. Bitte kontaktieren Sie den Administrator, um die URL Ihrer Website zur Liste hinzuzufügen.",
|
|
42374
|
+
"aboutTitle": "Über",
|
|
42375
|
+
"aboutVersion": "SDK-Version",
|
|
42376
|
+
"aboutConversationId": "Letzte Konversations-ID",
|
|
42377
|
+
"aboutNoConversation": "Noch keine Konversation"
|
|
41421
42378
|
}
|
|
41422
42379
|
});
|
|
41423
42380
|
|