ttp-agent-sdk 2.45.6 → 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 +1657 -714
- 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
|
|
@@ -23039,208 +23229,300 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
23039
23229
|
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; }
|
|
23040
23230
|
/**
|
|
23041
23231
|
* DOM Context Extraction
|
|
23042
|
-
*
|
|
23043
|
-
* Extracts
|
|
23044
|
-
*
|
|
23232
|
+
*
|
|
23233
|
+
* Extracts the actual readable content of the page — text, headings, code
|
|
23234
|
+
* blocks, lists — plus interactive elements (buttons, forms, links) for
|
|
23235
|
+
* navigation and action context.
|
|
23045
23236
|
*/
|
|
23046
23237
|
|
|
23047
23238
|
|
|
23048
|
-
|
|
23049
|
-
// Default limits to prevent token explosion
|
|
23050
23239
|
var DEFAULT_LIMITS = {
|
|
23240
|
+
maxContentLength: 8000,
|
|
23241
|
+
// chars of main text content
|
|
23242
|
+
maxCodeBlockLength: 600,
|
|
23243
|
+
// chars per code block
|
|
23051
23244
|
buttons: 20,
|
|
23052
23245
|
links: 30,
|
|
23053
23246
|
forms: 5,
|
|
23054
23247
|
fieldsPerForm: 15,
|
|
23055
|
-
|
|
23056
|
-
headings: 15,
|
|
23057
|
-
maxTextLength: 100,
|
|
23058
|
-
maxSummaryLength: 150
|
|
23248
|
+
maxTextLength: 100 // per interactive element label
|
|
23059
23249
|
};
|
|
23060
23250
|
|
|
23061
|
-
|
|
23062
|
-
|
|
23063
|
-
|
|
23064
|
-
|
|
23065
|
-
|
|
23066
|
-
|
|
23067
|
-
|
|
23068
|
-
|
|
23069
|
-
var
|
|
23070
|
-
|
|
23071
|
-
|
|
23072
|
-
|
|
23073
|
-
|
|
23074
|
-
return "[data-testid=\"".concat(element.dataset.testid, "\"]");
|
|
23075
|
-
}
|
|
23076
|
-
|
|
23077
|
-
// Priority 2: data-cy (Cypress test attribute)
|
|
23078
|
-
if ((_element$dataset2 = element.dataset) !== null && _element$dataset2 !== void 0 && _element$dataset2.cy) {
|
|
23079
|
-
return "[data-cy=\"".concat(element.dataset.cy, "\"]");
|
|
23080
|
-
}
|
|
23081
|
-
|
|
23082
|
-
// Priority 3: aria-label (accessibility, usually stable)
|
|
23083
|
-
var ariaLabel = element.getAttribute('aria-label');
|
|
23084
|
-
if (ariaLabel && ariaLabel.length < 50) {
|
|
23085
|
-
return "[aria-label=\"".concat(ariaLabel.replace(/"/g, '\\"'), "\"]");
|
|
23086
|
-
}
|
|
23087
|
-
|
|
23088
|
-
// Priority 4: Stable ID (not auto-generated)
|
|
23089
|
-
if (element.id && !isAutoGeneratedId(element.id)) {
|
|
23090
|
-
return "#".concat(CSS.escape(element.id));
|
|
23091
|
-
}
|
|
23092
|
-
|
|
23093
|
-
// Priority 5: name attribute (for form fields)
|
|
23094
|
-
if (element.name) {
|
|
23095
|
-
var tag = element.tagName.toLowerCase();
|
|
23096
|
-
return "".concat(tag, "[name=\"").concat(element.name, "\"]");
|
|
23097
|
-
}
|
|
23251
|
+
// ─── Noise exclusion ────────────────────────────────────────────────────────
|
|
23252
|
+
|
|
23253
|
+
var NOISE_TAGS = new Set(['nav', 'header', 'footer', 'aside', 'script', 'style', 'noscript', 'svg', 'canvas', 'iframe']);
|
|
23254
|
+
var NOISE_ROLES = new Set(['navigation', 'banner', 'complementary', 'search']);
|
|
23255
|
+
function isNoise(el) {
|
|
23256
|
+
if (NOISE_TAGS.has(el.tagName.toLowerCase())) return true;
|
|
23257
|
+
var role = el.getAttribute('role');
|
|
23258
|
+
if (role && NOISE_ROLES.has(role)) return true;
|
|
23259
|
+
var cls = el.className || '';
|
|
23260
|
+
// Common sidebar/nav class patterns
|
|
23261
|
+
if (/\b(sidebar|navbar|topbar|breadcrumb|cookie|toast|modal-backdrop)\b/i.test(cls)) return true;
|
|
23262
|
+
return false;
|
|
23263
|
+
}
|
|
23098
23264
|
|
|
23099
|
-
|
|
23100
|
-
if (['BUTTON', 'A'].includes(element.tagName)) {
|
|
23101
|
-
var _element$innerText;
|
|
23102
|
-
var text = (_element$innerText = element.innerText) === null || _element$innerText === void 0 ? void 0 : _element$innerText.trim();
|
|
23103
|
-
if (text && text.length < 30 && text.length > 0) {
|
|
23104
|
-
var _tag = element.tagName.toLowerCase();
|
|
23105
|
-
// Check if this text is unique on the page
|
|
23106
|
-
var matches = document.querySelectorAll("".concat(_tag));
|
|
23107
|
-
var sameTextCount = Array.from(matches).filter(function (el) {
|
|
23108
|
-
var _el$innerText;
|
|
23109
|
-
return ((_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim()) === text;
|
|
23110
|
-
}).length;
|
|
23111
|
-
if (sameTextCount === 1) {
|
|
23112
|
-
return "".concat(_tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
|
|
23113
|
-
}
|
|
23114
|
-
}
|
|
23115
|
-
}
|
|
23265
|
+
// ─── Visibility ──────────────────────────────────────────────────────────────
|
|
23116
23266
|
|
|
23117
|
-
|
|
23118
|
-
|
|
23267
|
+
function isVisible(el) {
|
|
23268
|
+
if (!el) return false;
|
|
23269
|
+
var style = window.getComputedStyle(el);
|
|
23270
|
+
return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' && el.offsetWidth > 0 && el.offsetHeight > 0;
|
|
23271
|
+
}
|
|
23272
|
+
function isInViewport(el) {
|
|
23273
|
+
var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
|
|
23274
|
+
var rect = el.getBoundingClientRect();
|
|
23275
|
+
return rect.bottom >= -buffer && rect.top <= window.innerHeight + buffer && rect.right >= 0 && rect.left <= window.innerWidth;
|
|
23119
23276
|
}
|
|
23120
23277
|
|
|
23121
|
-
|
|
23122
|
-
|
|
23123
|
-
*/
|
|
23278
|
+
// ─── Selector generation (kept for interactive elements) ─────────────────────
|
|
23279
|
+
|
|
23124
23280
|
function isAutoGeneratedId(id) {
|
|
23125
|
-
|
|
23126
|
-
|
|
23127
|
-
|
|
23128
|
-
|
|
23129
|
-
|
|
23130
|
-
|
|
23131
|
-
|
|
23132
|
-
|
|
23133
|
-
|
|
23134
|
-
// Ember
|
|
23135
|
-
/^_[a-z0-9]{8,}$/i,
|
|
23136
|
-
// Generic hash IDs
|
|
23137
|
-
/^[a-f0-9]{8}-[a-f0-9]{4}/i,
|
|
23138
|
-
// UUID-like
|
|
23139
|
-
/^uid-/i,
|
|
23140
|
-
// Generic UID
|
|
23141
|
-
/^id[0-9]+$/i // Generic numbered IDs
|
|
23142
|
-
];
|
|
23143
|
-
return autoGenPatterns.some(function (pattern) {
|
|
23144
|
-
return pattern.test(id);
|
|
23281
|
+
return /^(:r[0-9a-z]+:|react-|ng-|vue-|ember[0-9]+|_[a-z0-9]{8,}|[a-f0-9]{8}-[a-f0-9]{4}|uid-|id[0-9]+$)/i.test(id);
|
|
23282
|
+
}
|
|
23283
|
+
function getMeaningfulClass(el) {
|
|
23284
|
+
var utilityPatterns = [/^(flex|grid|block|inline|hidden)$/, /^(m|p|w|h|min|max)-/, /^(text|font|bg|border)-/, /^(col|row)-/, /^(sm|md|lg|xl|2xl):/, /^hover:|focus:|active:/, /^[a-z]{1,3}-[0-9]+$/];
|
|
23285
|
+
var classes = Array.from(el.classList || []);
|
|
23286
|
+
var meaningful = classes.filter(function (cls) {
|
|
23287
|
+
return !utilityPatterns.some(function (p) {
|
|
23288
|
+
return p.test(cls);
|
|
23289
|
+
}) && cls.length > 2 && cls.length < 30;
|
|
23145
23290
|
});
|
|
23291
|
+
return meaningful[0] || null;
|
|
23146
23292
|
}
|
|
23147
|
-
|
|
23148
|
-
/**
|
|
23149
|
-
* Build a selector path from ancestors
|
|
23150
|
-
*/
|
|
23151
|
-
function buildPathSelector(element) {
|
|
23293
|
+
function buildPathSelector(el) {
|
|
23152
23294
|
var maxDepth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
|
|
23153
23295
|
var path = [];
|
|
23154
|
-
var
|
|
23296
|
+
var cur = el;
|
|
23155
23297
|
var depth = 0;
|
|
23156
|
-
while (
|
|
23157
|
-
var tag =
|
|
23158
|
-
|
|
23159
|
-
|
|
23160
|
-
|
|
23161
|
-
|
|
23162
|
-
|
|
23163
|
-
|
|
23164
|
-
|
|
23165
|
-
// Add class if it seems meaningful
|
|
23166
|
-
var meaningfulClass = getMeaningfulClass(current);
|
|
23167
|
-
if (meaningfulClass) {
|
|
23168
|
-
path.unshift("".concat(tag, ".").concat(meaningfulClass));
|
|
23298
|
+
while (cur && cur !== document.body && depth < maxDepth) {
|
|
23299
|
+
var tag = cur.tagName.toLowerCase();
|
|
23300
|
+
if (cur.id && !isAutoGeneratedId(cur.id)) {
|
|
23301
|
+
path.unshift("#".concat(CSS.escape(cur.id)));
|
|
23302
|
+
break;
|
|
23303
|
+
}
|
|
23304
|
+
var cls = getMeaningfulClass(cur);
|
|
23305
|
+
if (cls) {
|
|
23306
|
+
path.unshift("".concat(tag, ".").concat(cls));
|
|
23169
23307
|
} else {
|
|
23170
|
-
var
|
|
23171
|
-
|
|
23172
|
-
var siblings = (_current$parentElemen = current.parentElement) === null || _current$parentElemen === void 0 ? void 0 : _current$parentElemen.children;
|
|
23308
|
+
var _cur$parentElement;
|
|
23309
|
+
var siblings = (_cur$parentElement = cur.parentElement) === null || _cur$parentElement === void 0 ? void 0 : _cur$parentElement.children;
|
|
23173
23310
|
if (siblings && siblings.length > 1) {
|
|
23174
|
-
var
|
|
23175
|
-
path.unshift("".concat(tag, ":nth-child(").concat(
|
|
23311
|
+
var idx = Array.from(siblings).indexOf(cur) + 1;
|
|
23312
|
+
path.unshift("".concat(tag, ":nth-child(").concat(idx, ")"));
|
|
23176
23313
|
} else {
|
|
23177
23314
|
path.unshift(tag);
|
|
23178
23315
|
}
|
|
23179
23316
|
}
|
|
23180
|
-
|
|
23317
|
+
cur = cur.parentElement;
|
|
23181
23318
|
depth++;
|
|
23182
23319
|
}
|
|
23183
23320
|
return path.join(' > ');
|
|
23184
23321
|
}
|
|
23322
|
+
function generateSelector(el) {
|
|
23323
|
+
var _el$dataset, _el$dataset2;
|
|
23324
|
+
if (!el || !el.tagName) return null;
|
|
23325
|
+
if ((_el$dataset = el.dataset) !== null && _el$dataset !== void 0 && _el$dataset.testid) return "[data-testid=\"".concat(el.dataset.testid, "\"]");
|
|
23326
|
+
if ((_el$dataset2 = el.dataset) !== null && _el$dataset2 !== void 0 && _el$dataset2.cy) return "[data-cy=\"".concat(el.dataset.cy, "\"]");
|
|
23327
|
+
var aria = el.getAttribute('aria-label');
|
|
23328
|
+
if (aria && aria.length < 50) return "[aria-label=\"".concat(aria.replace(/"/g, '\\"'), "\"]");
|
|
23329
|
+
if (el.id && !isAutoGeneratedId(el.id)) return "#".concat(CSS.escape(el.id));
|
|
23330
|
+
if (el.name) return "".concat(el.tagName.toLowerCase(), "[name=\"").concat(el.name, "\"]");
|
|
23331
|
+
if (['BUTTON', 'A'].includes(el.tagName)) {
|
|
23332
|
+
var _el$innerText;
|
|
23333
|
+
var text = (_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim();
|
|
23334
|
+
if (text && text.length < 30) {
|
|
23335
|
+
var tag = el.tagName.toLowerCase();
|
|
23336
|
+
var matches = document.querySelectorAll(tag);
|
|
23337
|
+
if (Array.from(matches).filter(function (e) {
|
|
23338
|
+
var _e$innerText;
|
|
23339
|
+
return ((_e$innerText = e.innerText) === null || _e$innerText === void 0 ? void 0 : _e$innerText.trim()) === text;
|
|
23340
|
+
}).length === 1) {
|
|
23341
|
+
return "".concat(tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
|
|
23342
|
+
}
|
|
23343
|
+
}
|
|
23344
|
+
}
|
|
23345
|
+
return buildPathSelector(el);
|
|
23346
|
+
}
|
|
23347
|
+
|
|
23348
|
+
// ─── Main content extraction ─────────────────────────────────────────────────
|
|
23185
23349
|
|
|
23186
23350
|
/**
|
|
23187
|
-
*
|
|
23351
|
+
* Find the best container element that holds the page's primary content.
|
|
23352
|
+
* Tries progressively wider selectors; falls back to document.body.
|
|
23188
23353
|
*/
|
|
23189
|
-
function
|
|
23190
|
-
var
|
|
23191
|
-
|
|
23192
|
-
|
|
23193
|
-
|
|
23194
|
-
|
|
23195
|
-
|
|
23196
|
-
|
|
23197
|
-
|
|
23198
|
-
|
|
23199
|
-
/^(sm|md|lg|xl|2xl):/,
|
|
23200
|
-
// Responsive
|
|
23201
|
-
/^hover:|focus:|active:/,
|
|
23202
|
-
// States
|
|
23203
|
-
/^[a-z]{1,3}-[0-9]+$/ // Generic utilities
|
|
23204
|
-
];
|
|
23205
|
-
var meaningfulClasses = classes.filter(function (cls) {
|
|
23206
|
-
return !utilityPatterns.some(function (pattern) {
|
|
23207
|
-
return pattern.test(cls);
|
|
23208
|
-
}) && cls.length > 2 && cls.length < 30;
|
|
23209
|
-
});
|
|
23210
|
-
return meaningfulClasses[0] || null;
|
|
23354
|
+
function findContentRoot() {
|
|
23355
|
+
var candidates = ['article', '[role="article"]', 'main', '[role="main"]', '.prose', '.markdown-body', '.content', '#content', '#main-content', '#main'];
|
|
23356
|
+
for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
|
|
23357
|
+
var sel = _candidates[_i];
|
|
23358
|
+
try {
|
|
23359
|
+
var el = document.querySelector(sel);
|
|
23360
|
+
if (el && isVisible(el)) return el;
|
|
23361
|
+
} catch (_unused) {}
|
|
23362
|
+
}
|
|
23363
|
+
return document.body;
|
|
23211
23364
|
}
|
|
23212
23365
|
|
|
23213
23366
|
/**
|
|
23214
|
-
*
|
|
23367
|
+
* Walk the content root and emit structured content items.
|
|
23368
|
+
* Skips noise elements (nav, header, aside…).
|
|
23369
|
+
*
|
|
23370
|
+
* Returns an array of items:
|
|
23371
|
+
* { type: 'heading', level: 'h2', text: '...' }
|
|
23372
|
+
* { type: 'text', text: '...' }
|
|
23373
|
+
* { type: 'code', lang: 'bash', text: '...' }
|
|
23374
|
+
* { type: 'listItem', text: '...' }
|
|
23215
23375
|
*/
|
|
23216
|
-
function
|
|
23217
|
-
var
|
|
23218
|
-
var
|
|
23219
|
-
|
|
23376
|
+
function walkContent(root, limits) {
|
|
23377
|
+
var items = [];
|
|
23378
|
+
var charCount = 0;
|
|
23379
|
+
var BLOCK_TAGS = new Set(['p', 'li', 'dt', 'dd', 'td', 'th', 'blockquote', 'figcaption']);
|
|
23380
|
+
var HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
|
|
23381
|
+
function walk(node) {
|
|
23382
|
+
if (charCount >= limits.maxContentLength) return;
|
|
23383
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return;
|
|
23384
|
+
var tag = node.tagName.toLowerCase();
|
|
23385
|
+
|
|
23386
|
+
// Skip noise subtrees entirely
|
|
23387
|
+
if (isNoise(node)) return;
|
|
23388
|
+
if (!isVisible(node)) return;
|
|
23389
|
+
|
|
23390
|
+
// Heading → new section marker
|
|
23391
|
+
if (HEADING_TAGS.has(tag)) {
|
|
23392
|
+
var text = (node.innerText || '').trim();
|
|
23393
|
+
if (text) {
|
|
23394
|
+
items.push({
|
|
23395
|
+
type: 'heading',
|
|
23396
|
+
level: tag,
|
|
23397
|
+
text: text
|
|
23398
|
+
});
|
|
23399
|
+
charCount += text.length;
|
|
23400
|
+
}
|
|
23401
|
+
return; // don't recurse — heading text already captured
|
|
23402
|
+
}
|
|
23403
|
+
|
|
23404
|
+
// Code block
|
|
23405
|
+
if (tag === 'pre') {
|
|
23406
|
+
var codeEl = node.querySelector('code');
|
|
23407
|
+
var raw = (codeEl || node).innerText || '';
|
|
23408
|
+
var _text = raw.trim().substring(0, limits.maxCodeBlockLength);
|
|
23409
|
+
if (_text) {
|
|
23410
|
+
var _match;
|
|
23411
|
+
var lang = ((_match = ((codeEl === null || codeEl === void 0 ? void 0 : codeEl.className) || '').match(/language-(\w+)/)) === null || _match === void 0 ? void 0 : _match[1]) || '';
|
|
23412
|
+
items.push({
|
|
23413
|
+
type: 'code',
|
|
23414
|
+
lang: lang,
|
|
23415
|
+
text: _text
|
|
23416
|
+
});
|
|
23417
|
+
charCount += _text.length;
|
|
23418
|
+
}
|
|
23419
|
+
return;
|
|
23420
|
+
}
|
|
23421
|
+
|
|
23422
|
+
// Inline code (not inside pre)
|
|
23423
|
+
if (tag === 'code' && node.closest('pre') === null) {
|
|
23424
|
+
// Let the parent block pick it up via innerText
|
|
23425
|
+
return;
|
|
23426
|
+
}
|
|
23427
|
+
|
|
23428
|
+
// Block-level text elements
|
|
23429
|
+
if (BLOCK_TAGS.has(tag)) {
|
|
23430
|
+
var _node$parentElement;
|
|
23431
|
+
// Skip if nested inside another block (e.g. <p> inside <blockquote> handled by blockquote)
|
|
23432
|
+
var parentTag = (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.tagName.toLowerCase();
|
|
23433
|
+
if (tag !== 'blockquote' && BLOCK_TAGS.has(parentTag) && parentTag !== 'li') return;
|
|
23434
|
+
var _text2 = (node.innerText || '').trim();
|
|
23435
|
+
if (_text2) {
|
|
23436
|
+
var type = tag === 'li' ? 'listItem' : 'text';
|
|
23437
|
+
var truncated = _text2.substring(0, 400);
|
|
23438
|
+
items.push({
|
|
23439
|
+
type: type,
|
|
23440
|
+
text: truncated
|
|
23441
|
+
});
|
|
23442
|
+
charCount += truncated.length;
|
|
23443
|
+
}
|
|
23444
|
+
return; // innerText already captures children
|
|
23445
|
+
}
|
|
23446
|
+
|
|
23447
|
+
// Container — recurse into children
|
|
23448
|
+
var _iterator = _createForOfIteratorHelper(node.children),
|
|
23449
|
+
_step;
|
|
23450
|
+
try {
|
|
23451
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
23452
|
+
var child = _step.value;
|
|
23453
|
+
if (charCount >= limits.maxContentLength) break;
|
|
23454
|
+
walk(child);
|
|
23455
|
+
}
|
|
23456
|
+
} catch (err) {
|
|
23457
|
+
_iterator.e(err);
|
|
23458
|
+
} finally {
|
|
23459
|
+
_iterator.f();
|
|
23460
|
+
}
|
|
23461
|
+
}
|
|
23462
|
+
walk(root);
|
|
23463
|
+
return items;
|
|
23220
23464
|
}
|
|
23221
23465
|
|
|
23222
23466
|
/**
|
|
23223
|
-
*
|
|
23467
|
+
* Convert structured content items into a readable flat string,
|
|
23468
|
+
* organised by heading sections.
|
|
23224
23469
|
*/
|
|
23225
|
-
function
|
|
23226
|
-
|
|
23227
|
-
var
|
|
23228
|
-
|
|
23470
|
+
function itemsToText(items) {
|
|
23471
|
+
var text = '';
|
|
23472
|
+
var _iterator2 = _createForOfIteratorHelper(items),
|
|
23473
|
+
_step2;
|
|
23474
|
+
try {
|
|
23475
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
23476
|
+
var item = _step2.value;
|
|
23477
|
+
switch (item.type) {
|
|
23478
|
+
case 'heading':
|
|
23479
|
+
text += "\n".concat('#'.repeat(parseInt(item.level[1])), " ").concat(item.text, "\n");
|
|
23480
|
+
break;
|
|
23481
|
+
case 'text':
|
|
23482
|
+
text += "".concat(item.text, "\n");
|
|
23483
|
+
break;
|
|
23484
|
+
case 'listItem':
|
|
23485
|
+
text += "\u2022 ".concat(item.text, "\n");
|
|
23486
|
+
break;
|
|
23487
|
+
case 'code':
|
|
23488
|
+
text += "```".concat(item.lang, "\n").concat(item.text, "\n```\n");
|
|
23489
|
+
break;
|
|
23490
|
+
}
|
|
23491
|
+
}
|
|
23492
|
+
} catch (err) {
|
|
23493
|
+
_iterator2.e(err);
|
|
23494
|
+
} finally {
|
|
23495
|
+
_iterator2.f();
|
|
23496
|
+
}
|
|
23497
|
+
return text.trim();
|
|
23229
23498
|
}
|
|
23230
23499
|
|
|
23231
23500
|
/**
|
|
23232
|
-
* Extract
|
|
23501
|
+
* Extract the main readable content of the page.
|
|
23233
23502
|
*/
|
|
23234
|
-
function
|
|
23235
|
-
var
|
|
23503
|
+
function extractMainContent(limits) {
|
|
23504
|
+
var root = findContentRoot();
|
|
23505
|
+
var items = walkContent(root, limits);
|
|
23506
|
+
var text = itemsToText(items);
|
|
23507
|
+
var truncated = text.length >= limits.maxContentLength;
|
|
23508
|
+
return {
|
|
23509
|
+
text: text,
|
|
23510
|
+
items: items,
|
|
23511
|
+
truncated: truncated,
|
|
23512
|
+
sourceElement: root.tagName.toLowerCase() + (root.id ? "#".concat(root.id) : '') + (getMeaningfulClass(root) ? ".".concat(getMeaningfulClass(root)) : '')
|
|
23513
|
+
};
|
|
23514
|
+
}
|
|
23515
|
+
|
|
23516
|
+
// ─── Interactive elements ─────────────────────────────────────────────────────
|
|
23517
|
+
|
|
23518
|
+
function extractButtons(limits) {
|
|
23236
23519
|
var buttons = [];
|
|
23237
|
-
var
|
|
23238
|
-
var
|
|
23239
|
-
|
|
23240
|
-
_step;
|
|
23520
|
+
var els = document.querySelectorAll('button, [type="submit"], [type="button"], [role="button"], .btn, .button');
|
|
23521
|
+
var _iterator3 = _createForOfIteratorHelper(els),
|
|
23522
|
+
_step3;
|
|
23241
23523
|
try {
|
|
23242
|
-
for (
|
|
23243
|
-
var el =
|
|
23524
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
23525
|
+
var el = _step3.value;
|
|
23244
23526
|
if (buttons.length >= limits.buttons) break;
|
|
23245
23527
|
if (!isVisible(el)) continue;
|
|
23246
23528
|
var text = (el.innerText || el.value || el.getAttribute('aria-label') || '').trim();
|
|
@@ -23254,101 +23536,76 @@ function extractButtons() {
|
|
|
23254
23536
|
});
|
|
23255
23537
|
}
|
|
23256
23538
|
} catch (err) {
|
|
23257
|
-
|
|
23539
|
+
_iterator3.e(err);
|
|
23258
23540
|
} finally {
|
|
23259
|
-
|
|
23541
|
+
_iterator3.f();
|
|
23260
23542
|
}
|
|
23261
23543
|
return buttons;
|
|
23262
23544
|
}
|
|
23263
|
-
|
|
23264
|
-
/**
|
|
23265
|
-
* Extract links from the page
|
|
23266
|
-
*/
|
|
23267
|
-
function extractLinks() {
|
|
23268
|
-
var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
|
|
23545
|
+
function extractLinks(limits) {
|
|
23269
23546
|
var links = [];
|
|
23270
|
-
var
|
|
23271
|
-
var
|
|
23272
|
-
var
|
|
23273
|
-
|
|
23547
|
+
var els = document.querySelectorAll('a[href]');
|
|
23548
|
+
var origin = window.location.origin;
|
|
23549
|
+
var _iterator4 = _createForOfIteratorHelper(els),
|
|
23550
|
+
_step4;
|
|
23274
23551
|
try {
|
|
23275
|
-
for (
|
|
23276
|
-
var el =
|
|
23552
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
23553
|
+
var el = _step4.value;
|
|
23277
23554
|
if (links.length >= limits.links) break;
|
|
23278
23555
|
if (!isVisible(el)) continue;
|
|
23279
23556
|
var text = (el.innerText || el.getAttribute('aria-label') || '').trim();
|
|
23280
23557
|
if (!text || text.length < 2) continue;
|
|
23281
|
-
|
|
23282
|
-
// Skip anchor links and javascript:void
|
|
23283
23558
|
var href = el.href;
|
|
23284
23559
|
if (!href || href.startsWith('javascript:') || href === '#') continue;
|
|
23285
|
-
var
|
|
23560
|
+
var internal = false;
|
|
23286
23561
|
try {
|
|
23287
|
-
|
|
23288
|
-
} catch (
|
|
23562
|
+
internal = new URL(href).origin === origin;
|
|
23563
|
+
} catch (_unused2) {}
|
|
23289
23564
|
links.push({
|
|
23290
23565
|
selector: generateSelector(el),
|
|
23291
23566
|
text: text.substring(0, limits.maxTextLength),
|
|
23292
23567
|
href: href,
|
|
23293
|
-
internal:
|
|
23568
|
+
internal: internal,
|
|
23294
23569
|
inViewport: isInViewport(el, 0)
|
|
23295
23570
|
});
|
|
23296
23571
|
}
|
|
23297
23572
|
} catch (err) {
|
|
23298
|
-
|
|
23573
|
+
_iterator4.e(err);
|
|
23299
23574
|
} finally {
|
|
23300
|
-
|
|
23575
|
+
_iterator4.f();
|
|
23301
23576
|
}
|
|
23302
23577
|
return links;
|
|
23303
23578
|
}
|
|
23304
|
-
|
|
23305
|
-
/**
|
|
23306
|
-
* Extract forms from the page (with sensitive field filtering)
|
|
23307
|
-
*/
|
|
23308
|
-
function extractForms() {
|
|
23309
|
-
var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
|
|
23579
|
+
function extractForms(limits) {
|
|
23310
23580
|
var forms = [];
|
|
23311
|
-
var elements = document.querySelectorAll('form');
|
|
23312
23581
|
var sensitiveCount = 0;
|
|
23313
|
-
var
|
|
23314
|
-
|
|
23582
|
+
var _iterator5 = _createForOfIteratorHelper(document.querySelectorAll('form')),
|
|
23583
|
+
_step5;
|
|
23315
23584
|
try {
|
|
23316
|
-
for (
|
|
23317
|
-
var form =
|
|
23585
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
23586
|
+
var form = _step5.value;
|
|
23318
23587
|
if (forms.length >= limits.forms) break;
|
|
23319
23588
|
if (!isVisible(form)) continue;
|
|
23320
23589
|
var fields = [];
|
|
23321
|
-
var
|
|
23322
|
-
|
|
23323
|
-
_step4;
|
|
23590
|
+
var _iterator6 = _createForOfIteratorHelper(form.querySelectorAll('input, textarea, select')),
|
|
23591
|
+
_step6;
|
|
23324
23592
|
try {
|
|
23325
|
-
for (
|
|
23593
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
23326
23594
|
var _label, _field$placeholder;
|
|
23327
|
-
var field =
|
|
23595
|
+
var field = _step6.value;
|
|
23328
23596
|
if (fields.length >= limits.fieldsPerForm) break;
|
|
23329
|
-
|
|
23330
|
-
// Skip hidden fields
|
|
23331
23597
|
if (field.type === 'hidden') continue;
|
|
23332
|
-
|
|
23333
|
-
// IMPORTANT: Filter sensitive fields
|
|
23334
23598
|
if ((0,_sensitive_filter_js__WEBPACK_IMPORTED_MODULE_0__.isSensitiveField)(field)) {
|
|
23335
23599
|
sensitiveCount++;
|
|
23336
23600
|
continue;
|
|
23337
23601
|
}
|
|
23338
|
-
|
|
23339
|
-
// Get label
|
|
23340
23602
|
var label = null;
|
|
23341
23603
|
if (field.id) {
|
|
23342
|
-
var
|
|
23343
|
-
var
|
|
23344
|
-
label =
|
|
23345
|
-
}
|
|
23346
|
-
if (!label && field.getAttribute('aria-label')) {
|
|
23347
|
-
label = field.getAttribute('aria-label');
|
|
23348
|
-
}
|
|
23349
|
-
if (!label && field.placeholder) {
|
|
23350
|
-
label = field.placeholder;
|
|
23604
|
+
var _lEl$innerText;
|
|
23605
|
+
var lEl = document.querySelector("label[for=\"".concat(field.id, "\"]"));
|
|
23606
|
+
label = lEl === null || lEl === void 0 || (_lEl$innerText = lEl.innerText) === null || _lEl$innerText === void 0 ? void 0 : _lEl$innerText.trim();
|
|
23351
23607
|
}
|
|
23608
|
+
label = label || field.getAttribute('aria-label') || field.placeholder || null;
|
|
23352
23609
|
fields.push({
|
|
23353
23610
|
selector: generateSelector(field),
|
|
23354
23611
|
name: field.name || null,
|
|
@@ -23356,15 +23613,14 @@ function extractForms() {
|
|
|
23356
23613
|
label: ((_label = label) === null || _label === void 0 ? void 0 : _label.substring(0, 50)) || null,
|
|
23357
23614
|
placeholder: ((_field$placeholder = field.placeholder) === null || _field$placeholder === void 0 ? void 0 : _field$placeholder.substring(0, 50)) || null,
|
|
23358
23615
|
required: field.required || false
|
|
23359
|
-
// NEVER include value for security
|
|
23360
23616
|
});
|
|
23361
23617
|
}
|
|
23362
23618
|
} catch (err) {
|
|
23363
|
-
|
|
23619
|
+
_iterator6.e(err);
|
|
23364
23620
|
} finally {
|
|
23365
|
-
|
|
23621
|
+
_iterator6.f();
|
|
23366
23622
|
}
|
|
23367
|
-
if (fields.length
|
|
23623
|
+
if (!fields.length) continue;
|
|
23368
23624
|
forms.push({
|
|
23369
23625
|
selector: generateSelector(form),
|
|
23370
23626
|
id: form.id || null,
|
|
@@ -23374,9 +23630,9 @@ function extractForms() {
|
|
|
23374
23630
|
});
|
|
23375
23631
|
}
|
|
23376
23632
|
} catch (err) {
|
|
23377
|
-
|
|
23633
|
+
_iterator5.e(err);
|
|
23378
23634
|
} finally {
|
|
23379
|
-
|
|
23635
|
+
_iterator5.f();
|
|
23380
23636
|
}
|
|
23381
23637
|
return {
|
|
23382
23638
|
forms: forms,
|
|
@@ -23384,143 +23640,56 @@ function extractForms() {
|
|
|
23384
23640
|
};
|
|
23385
23641
|
}
|
|
23386
23642
|
|
|
23387
|
-
|
|
23388
|
-
* Extract sections/landmarks from the page
|
|
23389
|
-
*/
|
|
23390
|
-
function extractSections() {
|
|
23391
|
-
var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
|
|
23392
|
-
var sections = [];
|
|
23393
|
-
var selector = 'section, article, main, [role="main"], [role="region"], .section';
|
|
23394
|
-
var elements = document.querySelectorAll(selector);
|
|
23395
|
-
var _iterator5 = _createForOfIteratorHelper(elements),
|
|
23396
|
-
_step5;
|
|
23397
|
-
try {
|
|
23398
|
-
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
23399
|
-
var _heading$innerText, _firstP$innerText, _el$innerText2;
|
|
23400
|
-
var el = _step5.value;
|
|
23401
|
-
if (sections.length >= limits.sections) break;
|
|
23402
|
-
if (!isVisible(el)) continue;
|
|
23403
|
-
|
|
23404
|
-
// Get a summary of the section content
|
|
23405
|
-
var heading = el.querySelector('h1, h2, h3');
|
|
23406
|
-
var headingText = (heading === null || heading === void 0 || (_heading$innerText = heading.innerText) === null || _heading$innerText === void 0 ? void 0 : _heading$innerText.trim()) || '';
|
|
23407
|
-
|
|
23408
|
-
// Get first paragraph or first N characters
|
|
23409
|
-
var firstP = el.querySelector('p');
|
|
23410
|
-
var summary = headingText || (firstP === null || firstP === void 0 || (_firstP$innerText = firstP.innerText) === null || _firstP$innerText === void 0 ? void 0 : _firstP$innerText.trim().substring(0, limits.maxSummaryLength)) || ((_el$innerText2 = el.innerText) === null || _el$innerText2 === void 0 ? void 0 : _el$innerText2.trim().substring(0, limits.maxSummaryLength)) || '';
|
|
23411
|
-
sections.push({
|
|
23412
|
-
selector: generateSelector(el),
|
|
23413
|
-
id: el.id || null,
|
|
23414
|
-
tagName: el.tagName.toLowerCase(),
|
|
23415
|
-
summary: summary.substring(0, limits.maxSummaryLength),
|
|
23416
|
-
inViewport: isInViewport(el, 0)
|
|
23417
|
-
});
|
|
23418
|
-
}
|
|
23419
|
-
} catch (err) {
|
|
23420
|
-
_iterator5.e(err);
|
|
23421
|
-
} finally {
|
|
23422
|
-
_iterator5.f();
|
|
23423
|
-
}
|
|
23424
|
-
return sections;
|
|
23425
|
-
}
|
|
23426
|
-
|
|
23427
|
-
/**
|
|
23428
|
-
* Extract headings from the page
|
|
23429
|
-
*/
|
|
23430
|
-
function extractHeadings() {
|
|
23431
|
-
var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
|
|
23432
|
-
var headings = [];
|
|
23433
|
-
var elements = document.querySelectorAll('h1, h2, h3');
|
|
23434
|
-
var _iterator6 = _createForOfIteratorHelper(elements),
|
|
23435
|
-
_step6;
|
|
23436
|
-
try {
|
|
23437
|
-
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
23438
|
-
var _el$innerText3;
|
|
23439
|
-
var el = _step6.value;
|
|
23440
|
-
if (headings.length >= limits.headings) break;
|
|
23441
|
-
if (!isVisible(el)) continue;
|
|
23442
|
-
var text = (_el$innerText3 = el.innerText) === null || _el$innerText3 === void 0 ? void 0 : _el$innerText3.trim();
|
|
23443
|
-
if (!text) continue;
|
|
23444
|
-
headings.push({
|
|
23445
|
-
selector: generateSelector(el),
|
|
23446
|
-
level: el.tagName.toLowerCase(),
|
|
23447
|
-
text: text.substring(0, limits.maxTextLength),
|
|
23448
|
-
inViewport: isInViewport(el, 0)
|
|
23449
|
-
});
|
|
23450
|
-
}
|
|
23451
|
-
} catch (err) {
|
|
23452
|
-
_iterator6.e(err);
|
|
23453
|
-
} finally {
|
|
23454
|
-
_iterator6.f();
|
|
23455
|
-
}
|
|
23456
|
-
return headings;
|
|
23457
|
-
}
|
|
23643
|
+
// ─── Public API ───────────────────────────────────────────────────────────────
|
|
23458
23644
|
|
|
23459
23645
|
/**
|
|
23460
|
-
* Main function
|
|
23461
|
-
*
|
|
23462
|
-
*
|
|
23463
|
-
*
|
|
23464
|
-
*
|
|
23646
|
+
* Main extraction function — called by the read_page tool handler.
|
|
23647
|
+
*
|
|
23648
|
+
* Returns:
|
|
23649
|
+
* content — flat readable text of the page (most important)
|
|
23650
|
+
* contentItems — structured array of { type, text, level?, lang? }
|
|
23651
|
+
* contentTruncated — true if content was cut at maxContentLength
|
|
23652
|
+
* url, title, language, viewport
|
|
23653
|
+
* buttons, links, forms — interactive elements for navigation / actions
|
|
23654
|
+
* metadata
|
|
23465
23655
|
*/
|
|
23466
23656
|
function extractDOMContext() {
|
|
23467
23657
|
return _extractDOMContext.apply(this, arguments);
|
|
23468
23658
|
}
|
|
23469
23659
|
|
|
23470
23660
|
/**
|
|
23471
|
-
*
|
|
23661
|
+
* Minimal context snapshot — used on reconnect / navigation events.
|
|
23472
23662
|
*/
|
|
23473
23663
|
function _extractDOMContext() {
|
|
23474
23664
|
_extractDOMContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
23475
23665
|
var _document$querySelect;
|
|
23476
23666
|
var options,
|
|
23477
23667
|
limits,
|
|
23668
|
+
mainContent,
|
|
23478
23669
|
buttons,
|
|
23479
23670
|
links,
|
|
23480
23671
|
_extractForms,
|
|
23481
23672
|
forms,
|
|
23482
23673
|
sensitiveCount,
|
|
23483
|
-
sections,
|
|
23484
|
-
headings,
|
|
23485
|
-
totalElements,
|
|
23486
|
-
visibleInViewport,
|
|
23487
23674
|
htmlLang,
|
|
23488
|
-
browserLang,
|
|
23489
23675
|
language,
|
|
23490
23676
|
_args = arguments;
|
|
23491
23677
|
return _regenerator().w(function (_context) {
|
|
23492
23678
|
while (1) switch (_context.n) {
|
|
23493
23679
|
case 0:
|
|
23494
23680
|
options = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
|
|
23495
|
-
limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits);
|
|
23681
|
+
limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits);
|
|
23682
|
+
mainContent = extractMainContent(limits);
|
|
23496
23683
|
buttons = extractButtons(limits);
|
|
23497
23684
|
links = extractLinks(limits);
|
|
23498
23685
|
_extractForms = extractForms(limits), forms = _extractForms.forms, sensitiveCount = _extractForms.sensitiveCount;
|
|
23499
|
-
sections = extractSections(limits);
|
|
23500
|
-
headings = extractHeadings(limits); // Count totals
|
|
23501
|
-
totalElements = buttons.length + links.length + forms.reduce(function (sum, f) {
|
|
23502
|
-
return sum + f.fields.length;
|
|
23503
|
-
}, 0) + sections.length + headings.length;
|
|
23504
|
-
visibleInViewport = buttons.filter(function (b) {
|
|
23505
|
-
return b.inViewport;
|
|
23506
|
-
}).length + links.filter(function (l) {
|
|
23507
|
-
return l.inViewport;
|
|
23508
|
-
}).length + sections.filter(function (s) {
|
|
23509
|
-
return s.inViewport;
|
|
23510
|
-
}).length + headings.filter(function (h) {
|
|
23511
|
-
return h.inViewport;
|
|
23512
|
-
}).length; // Detect site language
|
|
23513
|
-
// Priority: HTML lang attribute > browser language
|
|
23514
23686
|
htmlLang = document.documentElement.lang || ((_document$querySelect = document.querySelector('html')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.getAttribute('lang')) || null;
|
|
23515
|
-
|
|
23516
|
-
language = htmlLang || browserLang || null;
|
|
23687
|
+
language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
|
|
23517
23688
|
return _context.a(2, {
|
|
23518
23689
|
url: window.location.href,
|
|
23519
23690
|
title: document.title,
|
|
23520
23691
|
timestamp: Date.now(),
|
|
23521
23692
|
language: language,
|
|
23522
|
-
// Site language (from HTML lang attribute or browser)
|
|
23523
|
-
|
|
23524
23693
|
viewport: {
|
|
23525
23694
|
width: window.innerWidth,
|
|
23526
23695
|
height: window.innerHeight,
|
|
@@ -23528,14 +23697,20 @@ function _extractDOMContext() {
|
|
|
23528
23697
|
scrollY: window.scrollY,
|
|
23529
23698
|
pageHeight: document.documentElement.scrollHeight
|
|
23530
23699
|
},
|
|
23700
|
+
// ── Primary: actual page content ──────────────────────────────────────
|
|
23701
|
+
content: mainContent.text,
|
|
23702
|
+
contentItems: mainContent.items,
|
|
23703
|
+
contentTruncated: mainContent.truncated,
|
|
23704
|
+
contentSource: mainContent.sourceElement,
|
|
23705
|
+
// ── Secondary: interactive elements ───────────────────────────────────
|
|
23531
23706
|
buttons: buttons,
|
|
23532
23707
|
links: links,
|
|
23533
23708
|
forms: forms,
|
|
23534
|
-
sections: sections,
|
|
23535
|
-
headings: headings,
|
|
23536
23709
|
metadata: {
|
|
23537
|
-
|
|
23538
|
-
|
|
23710
|
+
totalContentChars: mainContent.text.length,
|
|
23711
|
+
contentItemCount: mainContent.items.length,
|
|
23712
|
+
buttonsCount: buttons.length,
|
|
23713
|
+
linksCount: links.length,
|
|
23539
23714
|
formsCount: forms.length,
|
|
23540
23715
|
sensitiveFieldsFiltered: sensitiveCount
|
|
23541
23716
|
}
|
|
@@ -23551,14 +23726,12 @@ function extractMinimalContext() {
|
|
|
23551
23726
|
function _extractMinimalContext() {
|
|
23552
23727
|
_extractMinimalContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
23553
23728
|
var _document$querySelect2;
|
|
23554
|
-
var htmlLang,
|
|
23729
|
+
var htmlLang, language;
|
|
23555
23730
|
return _regenerator().w(function (_context2) {
|
|
23556
23731
|
while (1) switch (_context2.n) {
|
|
23557
23732
|
case 0:
|
|
23558
|
-
// Detect site language
|
|
23559
23733
|
htmlLang = document.documentElement.lang || ((_document$querySelect2 = document.querySelector('html')) === null || _document$querySelect2 === void 0 ? void 0 : _document$querySelect2.getAttribute('lang')) || null;
|
|
23560
|
-
|
|
23561
|
-
language = htmlLang || browserLang || null;
|
|
23734
|
+
language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
|
|
23562
23735
|
return _context2.a(2, {
|
|
23563
23736
|
url: window.location.href,
|
|
23564
23737
|
title: document.title,
|
|
@@ -24039,16 +24212,19 @@ function registerVisualTools(registry) {
|
|
|
24039
24212
|
while (1) switch (_context.n) {
|
|
24040
24213
|
case 0:
|
|
24041
24214
|
params = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
|
|
24042
|
-
console.log('[TTP] 📋 Reading page
|
|
24215
|
+
console.log('[TTP] 📋 Reading page content...');
|
|
24043
24216
|
_context.n = 1;
|
|
24044
24217
|
return (0,_dom_context_js__WEBPACK_IMPORTED_MODULE_0__.extractDOMContext)(params);
|
|
24045
24218
|
case 1:
|
|
24046
24219
|
context = _context.v;
|
|
24047
|
-
console.log('[TTP] ✅ Page
|
|
24048
|
-
|
|
24049
|
-
|
|
24050
|
-
|
|
24051
|
-
|
|
24220
|
+
console.log('[TTP] ✅ Page content extracted:', {
|
|
24221
|
+
contentChars: context.metadata.totalContentChars,
|
|
24222
|
+
contentItems: context.metadata.contentItemCount,
|
|
24223
|
+
truncated: context.contentTruncated,
|
|
24224
|
+
source: context.contentSource,
|
|
24225
|
+
buttons: context.metadata.buttonsCount,
|
|
24226
|
+
links: context.metadata.linksCount,
|
|
24227
|
+
forms: context.metadata.formsCount
|
|
24052
24228
|
});
|
|
24053
24229
|
return _context.a(2, context);
|
|
24054
24230
|
}
|
|
@@ -24267,12 +24443,12 @@ function _extractPageContext() {
|
|
|
24267
24443
|
timestamp: domContext.timestamp,
|
|
24268
24444
|
language: domContext.language,
|
|
24269
24445
|
viewport: domContext.viewport,
|
|
24446
|
+
content: domContext.content,
|
|
24447
|
+
contentTruncated: domContext.contentTruncated,
|
|
24270
24448
|
dom: {
|
|
24271
24449
|
buttons: domContext.buttons,
|
|
24272
24450
|
links: domContext.links,
|
|
24273
24451
|
forms: domContext.forms,
|
|
24274
|
-
sections: domContext.sections,
|
|
24275
|
-
headings: domContext.headings,
|
|
24276
24452
|
metadata: domContext.metadata
|
|
24277
24453
|
}
|
|
24278
24454
|
});
|
|
@@ -24420,9 +24596,17 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24420
24596
|
// Transcript sync
|
|
24421
24597
|
_this.pendingSentenceText = null; // Text waiting for first audio chunk
|
|
24422
24598
|
_this.pendingSynced = null; // Synced actions waiting for first audio chunk
|
|
24423
|
-
_this.sentenceTimings = []; // [{startTime, text, synced, displayed}, ...]
|
|
24599
|
+
_this.sentenceTimings = []; // [{segmentId, startTime, endTime, text, synced, displayed, doneReported}, ...]
|
|
24424
24600
|
_this.isCheckingTranscripts = false;
|
|
24425
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
|
+
|
|
24426
24610
|
// Flag to prevent queuing new audio after stopImmediate() is called (barge-in protection)
|
|
24427
24611
|
// This prevents race conditions where audio chunks arrive after stop but before sources are stopped
|
|
24428
24612
|
// Cleared when markNewSentence() is called (signals new audio is starting)
|
|
@@ -24804,7 +24988,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24804
24988
|
// Keep scheduling frames as long as we have them and haven't reached the lookahead limit
|
|
24805
24989
|
scheduledCount = 0;
|
|
24806
24990
|
_loop = /*#__PURE__*/_regenerator().m(function _loop() {
|
|
24807
|
-
var preparedFrame, source, currentTime, isMobile, startupBuffer, minStartTime, startTime;
|
|
24991
|
+
var preparedFrame, source, currentTime, isMobile, startupBuffer, minStartTime, segFrameEnd, startTime;
|
|
24808
24992
|
return _regenerator().w(function (_context3) {
|
|
24809
24993
|
while (1) switch (_context3.n) {
|
|
24810
24994
|
case 0:
|
|
@@ -24864,22 +25048,32 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24864
25048
|
// Always use nextStartTime (which is already calculated for seamless playback)
|
|
24865
25049
|
}
|
|
24866
25050
|
|
|
24867
|
-
//
|
|
24868
|
-
|
|
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.
|
|
24869
25055
|
_this4.sentenceTimings.push({
|
|
25056
|
+
segmentId: _this4.pendingSegmentId,
|
|
24870
25057
|
startTime: _this4.nextStartTime,
|
|
25058
|
+
endTime: segFrameEnd,
|
|
24871
25059
|
text: _this4.pendingSentenceText,
|
|
24872
25060
|
synced: _this4.pendingSynced,
|
|
24873
|
-
displayed: false
|
|
25061
|
+
displayed: false,
|
|
25062
|
+
doneReported: false
|
|
24874
25063
|
});
|
|
24875
|
-
|
|
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, ")"));
|
|
24876
25066
|
_this4.pendingSentenceText = null;
|
|
24877
25067
|
_this4.pendingSynced = null;
|
|
25068
|
+
_this4.pendingSegmentId = null;
|
|
24878
25069
|
|
|
24879
25070
|
// Start checker if not running
|
|
24880
25071
|
if (!_this4.isCheckingTranscripts) {
|
|
24881
25072
|
_this4.startTranscriptChecker();
|
|
24882
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;
|
|
24883
25077
|
}
|
|
24884
25078
|
|
|
24885
25079
|
// Schedule this chunk to start at nextStartTime
|
|
@@ -24934,8 +25128,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24934
25128
|
if (_this4.scheduledBuffers === 0 && _this4.preparedBuffer.length === 0 && _this4.pcmChunkQueue.length === 0 && !_this4._isStopped) {
|
|
24935
25129
|
_this4.isPlaying = false;
|
|
24936
25130
|
_this4.isSchedulingFrames = false;
|
|
24937
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (all buffers finished)');
|
|
24938
|
-
_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
|
+
});
|
|
24939
25135
|
} else if (_this4.preparedBuffer.length > 0 && !_this4._isStopped) {
|
|
24940
25136
|
// More frames available, schedule them immediately
|
|
24941
25137
|
|
|
@@ -24971,8 +25167,10 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
24971
25167
|
};
|
|
24972
25168
|
if (!_this4.isPlaying) {
|
|
24973
25169
|
_this4.isPlaying = true;
|
|
24974
|
-
console.log('🎵 AudioPlayer: Emitting playbackStarted event');
|
|
24975
|
-
_this4.emit('playbackStarted'
|
|
25170
|
+
console.log('🎵 AudioPlayer: Emitting playbackStarted event (segmentId: ' + _this4.currentSegmentId + ')');
|
|
25171
|
+
_this4.emit('playbackStarted', {
|
|
25172
|
+
segmentId: _this4.currentSegmentId
|
|
25173
|
+
});
|
|
24976
25174
|
}
|
|
24977
25175
|
case 3:
|
|
24978
25176
|
return _context3.a(2);
|
|
@@ -26316,14 +26514,66 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26316
26514
|
// Note: scheduledBuffers was already reset to 0 above when clearing scheduledSources
|
|
26317
26515
|
this.nextStartTime = 0;
|
|
26318
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
|
+
|
|
26319
26567
|
// Clear transcript state
|
|
26320
26568
|
this.clearTranscriptState();
|
|
26321
26569
|
|
|
26322
26570
|
// Emit stopped event - CRITICAL for barge-in
|
|
26323
26571
|
|
|
26324
26572
|
if (wasPlaying) {
|
|
26325
|
-
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called)');
|
|
26326
|
-
this.emit('playbackStopped'
|
|
26573
|
+
console.log('🛑 AudioPlayer: Emitting playbackStopped event (stopImmediate called, segmentId: ' + stoppedSegmentId + ')');
|
|
26574
|
+
this.emit('playbackStopped', {
|
|
26575
|
+
segmentId: stoppedSegmentId
|
|
26576
|
+
});
|
|
26327
26577
|
}
|
|
26328
26578
|
}
|
|
26329
26579
|
|
|
@@ -26333,7 +26583,7 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26333
26583
|
*/
|
|
26334
26584
|
}, {
|
|
26335
26585
|
key: "markNewSentence",
|
|
26336
|
-
value: function markNewSentence(text, synced) {
|
|
26586
|
+
value: function markNewSentence(text, synced, segmentId) {
|
|
26337
26587
|
var _this0 = this;
|
|
26338
26588
|
var wasStopped = this._isStopped;
|
|
26339
26589
|
var isCurrentlyPlaying = this.isPlaying || this.scheduledSources.size > 0;
|
|
@@ -26378,10 +26628,12 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26378
26628
|
console.log("\uD83D\uDCDD AudioPlayer: New sentence queued while audio playing - will start after current sentence finishes");
|
|
26379
26629
|
}
|
|
26380
26630
|
|
|
26381
|
-
// 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).
|
|
26382
26633
|
this.pendingSentenceText = text;
|
|
26383
26634
|
this.pendingSynced = synced || null;
|
|
26384
|
-
|
|
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, ")"));
|
|
26385
26637
|
|
|
26386
26638
|
// CRITICAL: Set timeout to detect empty sentences (audio_start but no chunks)
|
|
26387
26639
|
// This prevents queue blocking if backend sends audio_start but no audio chunks follow
|
|
@@ -26393,6 +26645,18 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26393
26645
|
// Check if this sentence still has no chunks after timeout
|
|
26394
26646
|
if (_this0.pendingSentenceText === sentenceText && _this0.scheduledBuffers === 0 && _this0.preparedBuffer.length === 0 && _this0.pcmChunkQueue.length === 0 && !_this0._isStopped) {
|
|
26395
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
|
+
}
|
|
26396
26660
|
// Clear pending sentence to unblock next sentence
|
|
26397
26661
|
if (_this0.pendingSentenceText === sentenceText) {
|
|
26398
26662
|
_this0.pendingSentenceText = null;
|
|
@@ -26401,7 +26665,9 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26401
26665
|
// Only if we're not currently playing (to avoid interrupting real playback)
|
|
26402
26666
|
if (!_this0.isPlaying && _this0.scheduledSources.size === 0) {
|
|
26403
26667
|
console.log('🛑 AudioPlayer: Emitting playbackStopped for empty sentence timeout');
|
|
26404
|
-
_this0.emit('playbackStopped'
|
|
26668
|
+
_this0.emit('playbackStopped', {
|
|
26669
|
+
segmentId: _this0.currentSegmentId
|
|
26670
|
+
});
|
|
26405
26671
|
}
|
|
26406
26672
|
}
|
|
26407
26673
|
_this0._emptySentenceTimeout = null;
|
|
@@ -26421,34 +26687,67 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26421
26687
|
var _checkLoop = function checkLoop() {
|
|
26422
26688
|
if (!_this1.isCheckingTranscripts || !_this1.audioContext) return;
|
|
26423
26689
|
var currentTime = _this1.audioContext.currentTime;
|
|
26424
|
-
var
|
|
26425
|
-
|
|
26690
|
+
var _iterator2 = _createForOfIteratorHelper(_this1.sentenceTimings),
|
|
26691
|
+
_step2;
|
|
26426
26692
|
try {
|
|
26427
|
-
for (
|
|
26428
|
-
var
|
|
26429
|
-
if (!
|
|
26430
|
-
|
|
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;
|
|
26431
26697
|
var eventData = {
|
|
26432
|
-
text:
|
|
26698
|
+
text: _timing.text
|
|
26433
26699
|
};
|
|
26434
|
-
if (
|
|
26435
|
-
eventData.synced =
|
|
26700
|
+
if (_timing.synced) {
|
|
26701
|
+
eventData.synced = _timing.synced;
|
|
26436
26702
|
}
|
|
26437
|
-
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, ")"));
|
|
26438
26704
|
_this1.emit('transcriptDisplay', eventData);
|
|
26439
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
|
+
}
|
|
26440
26716
|
}
|
|
26441
26717
|
} catch (err) {
|
|
26442
|
-
|
|
26718
|
+
_iterator2.e(err);
|
|
26443
26719
|
} finally {
|
|
26444
|
-
|
|
26720
|
+
_iterator2.f();
|
|
26445
26721
|
}
|
|
26446
26722
|
if (_this1.isPlaying || _this1.scheduledBuffers > 0) {
|
|
26447
26723
|
requestAnimationFrame(_checkLoop);
|
|
26448
26724
|
} else {
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
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
|
+
}
|
|
26748
|
+
_this1.isCheckingTranscripts = false;
|
|
26749
|
+
console.log('📝 AudioPlayer: Transcript checker stopped');
|
|
26750
|
+
}
|
|
26452
26751
|
};
|
|
26453
26752
|
requestAnimationFrame(_checkLoop);
|
|
26454
26753
|
}
|
|
@@ -26461,6 +26760,8 @@ var AudioPlayer = /*#__PURE__*/function (_EventEmitter) {
|
|
|
26461
26760
|
value: function clearTranscriptState() {
|
|
26462
26761
|
this.pendingSentenceText = null;
|
|
26463
26762
|
this.pendingSynced = null;
|
|
26763
|
+
this.pendingSegmentId = null;
|
|
26764
|
+
this.currentSegmentId = null;
|
|
26464
26765
|
this.sentenceTimings = [];
|
|
26465
26766
|
this.isCheckingTranscripts = false;
|
|
26466
26767
|
console.log('📝 AudioPlayer: Transcript state cleared');
|
|
@@ -26610,13 +26911,13 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26610
26911
|
/* harmony import */ var _utils_screenshot_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/screenshot.js */ "./src/utils/screenshot.js");
|
|
26611
26912
|
/* harmony import */ var _utils_visual_tools_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/visual-tools.js */ "./src/utils/visual-tools.js");
|
|
26612
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; }
|
|
26613
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 }; })(); }
|
|
26614
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); }
|
|
26615
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); }
|
|
26616
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); }); }; }
|
|
26617
|
-
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; } } }; }
|
|
26618
|
-
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; } }
|
|
26619
|
-
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; }
|
|
26620
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; }
|
|
26621
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; }
|
|
26622
26923
|
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
|
|
@@ -27183,19 +27484,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27183
27484
|
key: "setupAudioPlayerEvents",
|
|
27184
27485
|
value: function setupAudioPlayerEvents() {
|
|
27185
27486
|
var _this3 = this;
|
|
27186
|
-
this.audioPlayer.on('playbackStarted', function () {
|
|
27487
|
+
this.audioPlayer.on('playbackStarted', function (info) {
|
|
27187
27488
|
_this3.isPlaying = true;
|
|
27188
27489
|
_this3.emit('playbackStarted');
|
|
27189
27490
|
|
|
27190
27491
|
// Transcripts are displayed when they arrive (between sentences)
|
|
27191
27492
|
// No need to handle transcript display here - it's handled in handleTranscript()
|
|
27192
27493
|
|
|
27193
|
-
// 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.
|
|
27194
27497
|
|
|
27195
27498
|
if (_this3.isConnected) {
|
|
27196
|
-
|
|
27499
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27500
|
+
console.log('📤 VoiceSDK v2: Sending audio_started_playing message to server (segmentId: ' + segmentId + ')');
|
|
27197
27501
|
_this3.sendMessage({
|
|
27198
|
-
t: 'audio_started_playing'
|
|
27502
|
+
t: 'audio_started_playing',
|
|
27503
|
+
segmentId: segmentId
|
|
27199
27504
|
});
|
|
27200
27505
|
} else {
|
|
27201
27506
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_started_playing - not connected');
|
|
@@ -27219,39 +27524,48 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27219
27524
|
_this3.emit('transcriptDisplay', fullTranscriptData);
|
|
27220
27525
|
_this3.emit('transcript', fullTranscriptData);
|
|
27221
27526
|
if (transcriptData.synced && Array.isArray(transcriptData.synced)) {
|
|
27222
|
-
console.log("\uD83D\uDCDD VoiceSDK v2:
|
|
27223
|
-
|
|
27224
|
-
_step;
|
|
27225
|
-
try {
|
|
27226
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
27227
|
-
var action = _step.value;
|
|
27228
|
-
_this3.emit('message', action);
|
|
27229
|
-
}
|
|
27230
|
-
} catch (err) {
|
|
27231
|
-
_iterator.e(err);
|
|
27232
|
-
} finally {
|
|
27233
|
-
_iterator.f();
|
|
27234
|
-
}
|
|
27527
|
+
console.log("\uD83D\uDCDD VoiceSDK v2: Dispatching ".concat(transcriptData.synced.length, " synced action(s)"));
|
|
27528
|
+
void _this3._dispatchSyncedActions(transcriptData.synced);
|
|
27235
27529
|
}
|
|
27236
27530
|
});
|
|
27237
|
-
this.audioPlayer.on('playbackStopped', function () {
|
|
27531
|
+
this.audioPlayer.on('playbackStopped', function (info) {
|
|
27238
27532
|
_this3.isPlaying = false;
|
|
27239
27533
|
_this3.emit('playbackStopped');
|
|
27240
27534
|
|
|
27241
27535
|
// When playback stops, keep currentPlayingSentenceId to track which sentence just finished
|
|
27242
27536
|
// The next transcript will arrive between sentences and will be displayed immediately
|
|
27243
27537
|
|
|
27244
|
-
// 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").
|
|
27245
27541
|
|
|
27246
27542
|
if (_this3.isConnected) {
|
|
27247
|
-
|
|
27543
|
+
var segmentId = info && info.segmentId != null ? info.segmentId : null;
|
|
27544
|
+
console.log('📤 VoiceSDK v2: Sending audio_stopped_playing message to server (segmentId: ' + segmentId + ')');
|
|
27248
27545
|
_this3.sendMessage({
|
|
27249
|
-
t: 'audio_stopped_playing'
|
|
27546
|
+
t: 'audio_stopped_playing',
|
|
27547
|
+
segmentId: segmentId
|
|
27250
27548
|
});
|
|
27251
27549
|
} else {
|
|
27252
27550
|
console.warn('⚠️ VoiceSDK v2: Cannot send audio_stopped_playing - not connected');
|
|
27253
27551
|
}
|
|
27254
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
|
+
});
|
|
27255
27569
|
this.audioPlayer.on('playbackError', function (error) {
|
|
27256
27570
|
_this3.emit('playbackError', error);
|
|
27257
27571
|
_this3.emit('error', error);
|
|
@@ -27616,7 +27930,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27616
27930
|
|
|
27617
27931
|
// Include SDK build time for debugging
|
|
27618
27932
|
if (true) {
|
|
27619
|
-
helloMessage.lastBuildTime = "2026-06-
|
|
27933
|
+
helloMessage.lastBuildTime = "2026-06-28T10:02:02.645Z";
|
|
27620
27934
|
}
|
|
27621
27935
|
|
|
27622
27936
|
// Page context is intentionally NOT attached to the hello message.
|
|
@@ -27771,7 +28085,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27771
28085
|
case 'audio_start':
|
|
27772
28086
|
// Backend sends audio_start with transcript text before audio chunks
|
|
27773
28087
|
// Store the text in AudioPlayer for synced display when audio actually starts playing
|
|
27774
|
-
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, ')');
|
|
27775
28089
|
|
|
27776
28090
|
// CRITICAL: Record timestamp to prevent premature stop_playing messages from cutting sentences
|
|
27777
28091
|
this.lastAudioStartTime = Date.now();
|
|
@@ -27787,7 +28101,10 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
27787
28101
|
if (synced) {
|
|
27788
28102
|
console.log("\uD83D\uDCDD VoiceSDK v2: audio_start carries ".concat(synced.length, " synced action(s)"));
|
|
27789
28103
|
}
|
|
27790
|
-
|
|
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);
|
|
27791
28108
|
}
|
|
27792
28109
|
// Also emit as message for other listeners
|
|
27793
28110
|
this.emit('message', message);
|
|
@@ -28316,6 +28633,104 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28316
28633
|
}
|
|
28317
28634
|
}
|
|
28318
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
|
+
}()
|
|
28319
28734
|
/**
|
|
28320
28735
|
* Handle a run_partner_script envelope (async partner-adapter dispatch).
|
|
28321
28736
|
*
|
|
@@ -28334,30 +28749,30 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28334
28749
|
}, {
|
|
28335
28750
|
key: "_handleRunPartnerScript",
|
|
28336
28751
|
value: (function () {
|
|
28337
|
-
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28752
|
+
var _handleRunPartnerScript2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(message) {
|
|
28338
28753
|
var _this$clientToolsRegi;
|
|
28339
|
-
var _ref, requestId, partnerId, action, args, handler, startedAt, result, elapsedMs, ok, reason, extras, preview, _elapsedMs,
|
|
28340
|
-
return _regenerator().w(function (
|
|
28341
|
-
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) {
|
|
28342
28757
|
case 0:
|
|
28343
28758
|
_ref = message || {}, requestId = _ref.requestId, partnerId = _ref.partnerId, action = _ref.action;
|
|
28344
28759
|
args = message && message.args || {};
|
|
28345
28760
|
if (requestId) {
|
|
28346
|
-
|
|
28761
|
+
_context5.n = 1;
|
|
28347
28762
|
break;
|
|
28348
28763
|
}
|
|
28349
28764
|
console.warn('⚠️ VoiceSDK v2: run_partner_script missing requestId; dropping', message);
|
|
28350
|
-
return
|
|
28765
|
+
return _context5.a(2);
|
|
28351
28766
|
case 1:
|
|
28352
28767
|
if (!_core_ClientScriptManager_js__WEBPACK_IMPORTED_MODULE_5__.ClientScriptManager.isClientToolsScript(message)) {
|
|
28353
|
-
|
|
28768
|
+
_context5.n = 2;
|
|
28354
28769
|
break;
|
|
28355
28770
|
}
|
|
28356
|
-
return
|
|
28771
|
+
return _context5.a(2, this.clientScriptManager.handleRunPartnerScript(message));
|
|
28357
28772
|
case 2:
|
|
28358
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');
|
|
28359
28774
|
if (handler) {
|
|
28360
|
-
|
|
28775
|
+
_context5.n = 3;
|
|
28361
28776
|
break;
|
|
28362
28777
|
}
|
|
28363
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));
|
|
@@ -28369,18 +28784,18 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28369
28784
|
ok: false,
|
|
28370
28785
|
error: 'no_handler_registered'
|
|
28371
28786
|
});
|
|
28372
|
-
return
|
|
28787
|
+
return _context5.a(2);
|
|
28373
28788
|
case 3:
|
|
28374
28789
|
startedAt = Date.now();
|
|
28375
28790
|
console.log("\uD83E\uDDE9 VoiceSDK v2: run_partner_script dispatch partner=".concat(partnerId, " action=").concat(action, " requestId=").concat(requestId));
|
|
28376
|
-
|
|
28377
|
-
|
|
28791
|
+
_context5.p = 4;
|
|
28792
|
+
_context5.n = 5;
|
|
28378
28793
|
return handler({
|
|
28379
28794
|
action: action,
|
|
28380
28795
|
args: args
|
|
28381
28796
|
});
|
|
28382
28797
|
case 5:
|
|
28383
|
-
result =
|
|
28798
|
+
result = _context5.v;
|
|
28384
28799
|
elapsedMs = Date.now() - startedAt; // Adapters return { ok, ... } themselves. Honor that flag if present;
|
|
28385
28800
|
// otherwise treat presence-of-result as success.
|
|
28386
28801
|
ok = result && _typeof(result) === 'object' && 'ok' in result ? !!result.ok : true; // Surface the failure reason inline so debugging doesn't require pulling
|
|
@@ -28407,27 +28822,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28407
28822
|
ok: ok,
|
|
28408
28823
|
result: result
|
|
28409
28824
|
});
|
|
28410
|
-
|
|
28825
|
+
_context5.n = 7;
|
|
28411
28826
|
break;
|
|
28412
28827
|
case 6:
|
|
28413
|
-
|
|
28414
|
-
|
|
28828
|
+
_context5.p = 6;
|
|
28829
|
+
_t4 = _context5.v;
|
|
28415
28830
|
_elapsedMs = Date.now() - startedAt;
|
|
28416
|
-
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);
|
|
28417
28832
|
this.sendMessage({
|
|
28418
28833
|
t: 'run_partner_script_result',
|
|
28419
28834
|
requestId: requestId,
|
|
28420
28835
|
partnerId: partnerId,
|
|
28421
28836
|
action: action,
|
|
28422
28837
|
ok: false,
|
|
28423
|
-
error:
|
|
28838
|
+
error: _t4 && _t4.message || String(_t4)
|
|
28424
28839
|
});
|
|
28425
28840
|
case 7:
|
|
28426
|
-
return
|
|
28841
|
+
return _context5.a(2);
|
|
28427
28842
|
}
|
|
28428
|
-
},
|
|
28843
|
+
}, _callee5, this, [[4, 6]]);
|
|
28429
28844
|
}));
|
|
28430
|
-
function _handleRunPartnerScript(
|
|
28845
|
+
function _handleRunPartnerScript(_x3) {
|
|
28431
28846
|
return _handleRunPartnerScript2.apply(this, arguments);
|
|
28432
28847
|
}
|
|
28433
28848
|
return _handleRunPartnerScript;
|
|
@@ -28472,7 +28887,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28472
28887
|
}, {
|
|
28473
28888
|
key: "injectData",
|
|
28474
28889
|
value: (function () {
|
|
28475
|
-
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28890
|
+
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
28476
28891
|
var _this7 = this;
|
|
28477
28892
|
var options,
|
|
28478
28893
|
trimmedData,
|
|
@@ -28483,15 +28898,15 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28483
28898
|
timeout,
|
|
28484
28899
|
source,
|
|
28485
28900
|
message,
|
|
28486
|
-
|
|
28487
|
-
return _regenerator().w(function (
|
|
28488
|
-
while (1) switch (
|
|
28901
|
+
_args6 = arguments;
|
|
28902
|
+
return _regenerator().w(function (_context6) {
|
|
28903
|
+
while (1) switch (_context6.n) {
|
|
28489
28904
|
case 0:
|
|
28490
|
-
options =
|
|
28905
|
+
options = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {};
|
|
28491
28906
|
// Validation: data content
|
|
28492
28907
|
trimmedData = data === null || data === void 0 ? void 0 : data.trim();
|
|
28493
28908
|
if (trimmedData) {
|
|
28494
|
-
|
|
28909
|
+
_context6.n = 1;
|
|
28495
28910
|
break;
|
|
28496
28911
|
}
|
|
28497
28912
|
error = {
|
|
@@ -28503,7 +28918,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28503
28918
|
throw new Error(error.message);
|
|
28504
28919
|
case 1:
|
|
28505
28920
|
if (!(!this.isConnected || !this.websocket)) {
|
|
28506
|
-
|
|
28921
|
+
_context6.n = 2;
|
|
28507
28922
|
break;
|
|
28508
28923
|
}
|
|
28509
28924
|
_error = {
|
|
@@ -28515,7 +28930,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28515
28930
|
throw new Error(_error.message);
|
|
28516
28931
|
case 2:
|
|
28517
28932
|
if (!(trimmedData.length > 5000)) {
|
|
28518
|
-
|
|
28933
|
+
_context6.n = 3;
|
|
28519
28934
|
break;
|
|
28520
28935
|
}
|
|
28521
28936
|
_error2 = {
|
|
@@ -28544,7 +28959,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28544
28959
|
}
|
|
28545
28960
|
|
|
28546
28961
|
// Return Promise that resolves when acknowledgment is received
|
|
28547
|
-
return
|
|
28962
|
+
return _context6.a(2, new Promise(function (_resolve, _reject) {
|
|
28548
28963
|
// Set up timeout
|
|
28549
28964
|
var timeoutId = setTimeout(function () {
|
|
28550
28965
|
// Remove from pending map
|
|
@@ -28595,9 +29010,9 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28595
29010
|
}
|
|
28596
29011
|
}));
|
|
28597
29012
|
}
|
|
28598
|
-
},
|
|
29013
|
+
}, _callee6, this);
|
|
28599
29014
|
}));
|
|
28600
|
-
function injectData(
|
|
29015
|
+
function injectData(_x4) {
|
|
28601
29016
|
return _injectData.apply(this, arguments);
|
|
28602
29017
|
}
|
|
28603
29018
|
return injectData;
|
|
@@ -28727,20 +29142,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28727
29142
|
}, {
|
|
28728
29143
|
key: "handleBinaryMessage",
|
|
28729
29144
|
value: (function () {
|
|
28730
|
-
var _handleBinaryMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
28731
|
-
var arrayBuffer, processedAudio, playbackFormat, container, encoding, pcmData, codec, decoded,
|
|
28732
|
-
return _regenerator().w(function (
|
|
28733
|
-
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) {
|
|
28734
29149
|
case 0:
|
|
28735
29150
|
if (!(data instanceof Blob)) {
|
|
28736
|
-
|
|
29151
|
+
_context7.n = 2;
|
|
28737
29152
|
break;
|
|
28738
29153
|
}
|
|
28739
|
-
|
|
29154
|
+
_context7.n = 1;
|
|
28740
29155
|
return data.arrayBuffer();
|
|
28741
29156
|
case 1:
|
|
28742
|
-
arrayBuffer =
|
|
28743
|
-
|
|
29157
|
+
arrayBuffer = _context7.v;
|
|
29158
|
+
_context7.n = 3;
|
|
28744
29159
|
break;
|
|
28745
29160
|
case 2:
|
|
28746
29161
|
arrayBuffer = data;
|
|
@@ -28748,21 +29163,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28748
29163
|
// Convert format if needed (before passing to AudioPlayer)
|
|
28749
29164
|
processedAudio = arrayBuffer;
|
|
28750
29165
|
if (!(this.formatConverter && this.formatConverter.needsConversion())) {
|
|
28751
|
-
|
|
29166
|
+
_context7.n = 7;
|
|
28752
29167
|
break;
|
|
28753
29168
|
}
|
|
28754
|
-
|
|
28755
|
-
|
|
29169
|
+
_context7.p = 4;
|
|
29170
|
+
_context7.n = 5;
|
|
28756
29171
|
return this.formatConverter.convert(arrayBuffer);
|
|
28757
29172
|
case 5:
|
|
28758
|
-
processedAudio =
|
|
29173
|
+
processedAudio = _context7.v;
|
|
28759
29174
|
console.log('✅ VoiceSDK v2: Audio converted to requested format');
|
|
28760
|
-
|
|
29175
|
+
_context7.n = 7;
|
|
28761
29176
|
break;
|
|
28762
29177
|
case 6:
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
console.error('❌ VoiceSDK v2: Format conversion failed:',
|
|
29178
|
+
_context7.p = 6;
|
|
29179
|
+
_t5 = _context7.v;
|
|
29180
|
+
console.error('❌ VoiceSDK v2: Format conversion failed:', _t5);
|
|
28766
29181
|
console.warn(' Using backend format without conversion');
|
|
28767
29182
|
processedAudio = arrayBuffer; // Fall back to original
|
|
28768
29183
|
case 7:
|
|
@@ -28812,11 +29227,11 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
28812
29227
|
this.audioPlayer.playAudio(processedAudio);
|
|
28813
29228
|
}
|
|
28814
29229
|
case 8:
|
|
28815
|
-
return
|
|
29230
|
+
return _context7.a(2);
|
|
28816
29231
|
}
|
|
28817
|
-
},
|
|
29232
|
+
}, _callee7, this, [[4, 6]]);
|
|
28818
29233
|
}));
|
|
28819
|
-
function handleBinaryMessage(
|
|
29234
|
+
function handleBinaryMessage(_x5) {
|
|
28820
29235
|
return _handleBinaryMessage.apply(this, arguments);
|
|
28821
29236
|
}
|
|
28822
29237
|
return handleBinaryMessage;
|
|
@@ -29004,22 +29419,22 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29004
29419
|
}, {
|
|
29005
29420
|
key: "startRecording",
|
|
29006
29421
|
value: (function () {
|
|
29007
|
-
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29422
|
+
var _startRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
29008
29423
|
var existingMediaStream,
|
|
29009
29424
|
error,
|
|
29010
29425
|
_error4,
|
|
29011
29426
|
_error5,
|
|
29012
29427
|
permissionError,
|
|
29013
|
-
|
|
29014
|
-
|
|
29015
|
-
|
|
29016
|
-
|
|
29017
|
-
return _regenerator().w(function (
|
|
29018
|
-
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) {
|
|
29019
29434
|
case 0:
|
|
29020
|
-
existingMediaStream =
|
|
29435
|
+
existingMediaStream = _args8.length > 0 && _args8[0] !== undefined ? _args8[0] : null;
|
|
29021
29436
|
if (this.isConnected) {
|
|
29022
|
-
|
|
29437
|
+
_context8.n = 1;
|
|
29023
29438
|
break;
|
|
29024
29439
|
}
|
|
29025
29440
|
error = new Error('Not connected to voice server');
|
|
@@ -29027,14 +29442,14 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29027
29442
|
throw error;
|
|
29028
29443
|
case 1:
|
|
29029
29444
|
if (!this.isRecording) {
|
|
29030
|
-
|
|
29445
|
+
_context8.n = 2;
|
|
29031
29446
|
break;
|
|
29032
29447
|
}
|
|
29033
29448
|
console.warn('VoiceSDK v2: Already recording');
|
|
29034
|
-
return
|
|
29449
|
+
return _context8.a(2, true);
|
|
29035
29450
|
case 2:
|
|
29036
29451
|
if (!this.disclaimersPending) {
|
|
29037
|
-
|
|
29452
|
+
_context8.n = 3;
|
|
29038
29453
|
break;
|
|
29039
29454
|
}
|
|
29040
29455
|
_error4 = new Error('Server disclaimers must be accepted before recording. Call sendDisclaimerAck(true) first.');
|
|
@@ -29043,28 +29458,28 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29043
29458
|
throw _error4;
|
|
29044
29459
|
case 3:
|
|
29045
29460
|
console.log('🎤 VoiceSDK v2: Starting recording...');
|
|
29046
|
-
|
|
29461
|
+
_context8.p = 4;
|
|
29047
29462
|
// CRITICAL for mobile browsers: Request microphone permission FIRST
|
|
29048
29463
|
// iOS: Pass existingMediaStream to avoid second getUserMedia (can fail on iOS)
|
|
29049
29464
|
console.log('🎤 VoiceSDK v2: Requesting microphone permission (mobile-friendly)...');
|
|
29050
|
-
|
|
29465
|
+
_context8.n = 5;
|
|
29051
29466
|
return this.audioRecorder.start(existingMediaStream ? {
|
|
29052
29467
|
existingMediaStream: existingMediaStream
|
|
29053
29468
|
} : {});
|
|
29054
29469
|
case 5:
|
|
29055
29470
|
if (!(!this.isConnected || !this.websocket || this.websocket.readyState !== WebSocket.OPEN)) {
|
|
29056
|
-
|
|
29471
|
+
_context8.n = 10;
|
|
29057
29472
|
break;
|
|
29058
29473
|
}
|
|
29059
|
-
|
|
29060
|
-
|
|
29474
|
+
_context8.p = 6;
|
|
29475
|
+
_context8.n = 7;
|
|
29061
29476
|
return this.audioRecorder.stop();
|
|
29062
29477
|
case 7:
|
|
29063
|
-
|
|
29478
|
+
_context8.n = 9;
|
|
29064
29479
|
break;
|
|
29065
29480
|
case 8:
|
|
29066
|
-
|
|
29067
|
-
|
|
29481
|
+
_context8.p = 8;
|
|
29482
|
+
_t6 = _context8.v;
|
|
29068
29483
|
case 9:
|
|
29069
29484
|
_error5 = new Error('Connection lost - server may have rejected the call');
|
|
29070
29485
|
_error5.name = 'ServerRejected';
|
|
@@ -29073,7 +29488,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29073
29488
|
// The error handler in VoiceInterface will handle it appropriately
|
|
29074
29489
|
throw _error5;
|
|
29075
29490
|
case 10:
|
|
29076
|
-
|
|
29491
|
+
_context8.n = 11;
|
|
29077
29492
|
return this.audioPlayer.resumeAudioContext();
|
|
29078
29493
|
case 11:
|
|
29079
29494
|
// After permission is granted, send start_continuous_mode message to server
|
|
@@ -29084,45 +29499,45 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29084
29499
|
|
|
29085
29500
|
// Request screen wake lock to keep screen on during voice call (mobile)
|
|
29086
29501
|
this._requestWakeLock();
|
|
29087
|
-
return
|
|
29502
|
+
return _context8.a(2, true);
|
|
29088
29503
|
case 12:
|
|
29089
|
-
|
|
29090
|
-
|
|
29504
|
+
_context8.p = 12;
|
|
29505
|
+
_t7 = _context8.v;
|
|
29091
29506
|
if (!(this.audioRecorder && this.audioRecorder.isRecording)) {
|
|
29092
|
-
|
|
29507
|
+
_context8.n = 16;
|
|
29093
29508
|
break;
|
|
29094
29509
|
}
|
|
29095
|
-
|
|
29096
|
-
|
|
29510
|
+
_context8.p = 13;
|
|
29511
|
+
_context8.n = 14;
|
|
29097
29512
|
return this.audioRecorder.stop();
|
|
29098
29513
|
case 14:
|
|
29099
|
-
|
|
29514
|
+
_context8.n = 16;
|
|
29100
29515
|
break;
|
|
29101
29516
|
case 15:
|
|
29102
|
-
|
|
29103
|
-
|
|
29517
|
+
_context8.p = 15;
|
|
29518
|
+
_t8 = _context8.v;
|
|
29104
29519
|
case 16:
|
|
29105
|
-
if (!(
|
|
29106
|
-
|
|
29520
|
+
if (!(_t7.isServerRejection || _t7.name === 'ServerRejected')) {
|
|
29521
|
+
_context8.n = 17;
|
|
29107
29522
|
break;
|
|
29108
29523
|
}
|
|
29109
|
-
return
|
|
29524
|
+
return _context8.a(2, false);
|
|
29110
29525
|
case 17:
|
|
29111
29526
|
// Log and emit other errors (permission denied, etc.)
|
|
29112
|
-
console.error('❌ VoiceSDK v2: Failed to start recording:',
|
|
29527
|
+
console.error('❌ VoiceSDK v2: Failed to start recording:', _t7);
|
|
29113
29528
|
|
|
29114
29529
|
// Provide helpful error messages for permission issues
|
|
29115
|
-
if (
|
|
29530
|
+
if (_t7.name === 'NotAllowedError' || _t7.name === 'PermissionDeniedError') {
|
|
29116
29531
|
permissionError = new Error('Microphone permission denied. Please allow microphone access in your browser settings and try again.');
|
|
29117
|
-
permissionError.name =
|
|
29118
|
-
permissionError.originalError =
|
|
29532
|
+
permissionError.name = _t7.name;
|
|
29533
|
+
permissionError.originalError = _t7;
|
|
29119
29534
|
this.emit('error', permissionError);
|
|
29120
29535
|
} else {
|
|
29121
|
-
this.emit('error',
|
|
29536
|
+
this.emit('error', _t7);
|
|
29122
29537
|
}
|
|
29123
|
-
return
|
|
29538
|
+
return _context8.a(2, false);
|
|
29124
29539
|
}
|
|
29125
|
-
},
|
|
29540
|
+
}, _callee8, this, [[13, 15], [6, 8], [4, 12]]);
|
|
29126
29541
|
}));
|
|
29127
29542
|
function startRecording() {
|
|
29128
29543
|
return _startRecording.apply(this, arguments);
|
|
@@ -29136,20 +29551,20 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29136
29551
|
}, {
|
|
29137
29552
|
key: "stopRecording",
|
|
29138
29553
|
value: (function () {
|
|
29139
|
-
var _stopRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29140
|
-
var
|
|
29141
|
-
return _regenerator().w(function (
|
|
29142
|
-
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) {
|
|
29143
29558
|
case 0:
|
|
29144
29559
|
if (this.isRecording) {
|
|
29145
|
-
|
|
29560
|
+
_context9.n = 1;
|
|
29146
29561
|
break;
|
|
29147
29562
|
}
|
|
29148
29563
|
console.warn('VoiceSDK v2: Not recording');
|
|
29149
|
-
return
|
|
29564
|
+
return _context9.a(2, true);
|
|
29150
29565
|
case 1:
|
|
29151
29566
|
console.log('🛑 VoiceSDK v2: Stopping recording...');
|
|
29152
|
-
|
|
29567
|
+
_context9.p = 2;
|
|
29153
29568
|
// Send stop_continuous_mode message to server
|
|
29154
29569
|
|
|
29155
29570
|
this.sendMessage({
|
|
@@ -29167,21 +29582,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29167
29582
|
this._releaseWakeLock();
|
|
29168
29583
|
|
|
29169
29584
|
// Stop capturing audio from microphone
|
|
29170
|
-
|
|
29585
|
+
_context9.n = 3;
|
|
29171
29586
|
return this.audioRecorder.stop();
|
|
29172
29587
|
case 3:
|
|
29173
29588
|
// Stop any playing audio
|
|
29174
29589
|
|
|
29175
29590
|
this.stopAudioPlayback();
|
|
29176
|
-
return
|
|
29591
|
+
return _context9.a(2, true);
|
|
29177
29592
|
case 4:
|
|
29178
|
-
|
|
29179
|
-
|
|
29180
|
-
console.error('VoiceSDK v2: Error stopping recording:',
|
|
29181
|
-
this.emit('error',
|
|
29182
|
-
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);
|
|
29183
29598
|
}
|
|
29184
|
-
},
|
|
29599
|
+
}, _callee9, this, [[2, 4]]);
|
|
29185
29600
|
}));
|
|
29186
29601
|
function stopRecording() {
|
|
29187
29602
|
return _stopRecording.apply(this, arguments);
|
|
@@ -29195,27 +29610,27 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29195
29610
|
}, {
|
|
29196
29611
|
key: "toggleRecording",
|
|
29197
29612
|
value: (function () {
|
|
29198
|
-
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29199
|
-
return _regenerator().w(function (
|
|
29200
|
-
while (1) switch (
|
|
29613
|
+
var _toggleRecording = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
29614
|
+
return _regenerator().w(function (_context0) {
|
|
29615
|
+
while (1) switch (_context0.n) {
|
|
29201
29616
|
case 0:
|
|
29202
29617
|
if (!this.isRecording) {
|
|
29203
|
-
|
|
29618
|
+
_context0.n = 2;
|
|
29204
29619
|
break;
|
|
29205
29620
|
}
|
|
29206
|
-
|
|
29621
|
+
_context0.n = 1;
|
|
29207
29622
|
return this.stopRecording();
|
|
29208
29623
|
case 1:
|
|
29209
|
-
return
|
|
29624
|
+
return _context0.a(2, _context0.v);
|
|
29210
29625
|
case 2:
|
|
29211
|
-
|
|
29626
|
+
_context0.n = 3;
|
|
29212
29627
|
return this.startRecording();
|
|
29213
29628
|
case 3:
|
|
29214
|
-
return
|
|
29629
|
+
return _context0.a(2, _context0.v);
|
|
29215
29630
|
case 4:
|
|
29216
|
-
return
|
|
29631
|
+
return _context0.a(2);
|
|
29217
29632
|
}
|
|
29218
|
-
},
|
|
29633
|
+
}, _callee0, this);
|
|
29219
29634
|
}));
|
|
29220
29635
|
function toggleRecording() {
|
|
29221
29636
|
return _toggleRecording.apply(this, arguments);
|
|
@@ -29246,33 +29661,33 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29246
29661
|
}, {
|
|
29247
29662
|
key: "_requestWakeLock",
|
|
29248
29663
|
value: (function () {
|
|
29249
|
-
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29664
|
+
var _requestWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
|
|
29250
29665
|
var _this9 = this;
|
|
29251
|
-
var
|
|
29252
|
-
return _regenerator().w(function (
|
|
29253
|
-
while (1) switch (
|
|
29666
|
+
var _t0;
|
|
29667
|
+
return _regenerator().w(function (_context1) {
|
|
29668
|
+
while (1) switch (_context1.p = _context1.n) {
|
|
29254
29669
|
case 0:
|
|
29255
29670
|
if ('wakeLock' in navigator) {
|
|
29256
|
-
|
|
29671
|
+
_context1.n = 1;
|
|
29257
29672
|
break;
|
|
29258
29673
|
}
|
|
29259
29674
|
console.log('📱 VoiceSDK v2: Wake Lock API not available in this browser');
|
|
29260
|
-
return
|
|
29675
|
+
return _context1.a(2);
|
|
29261
29676
|
case 1:
|
|
29262
29677
|
if (!(this.wakeLock !== null || this._wakeLockRequesting)) {
|
|
29263
|
-
|
|
29678
|
+
_context1.n = 2;
|
|
29264
29679
|
break;
|
|
29265
29680
|
}
|
|
29266
29681
|
console.log('📱 VoiceSDK v2: Wake lock already active or being requested');
|
|
29267
|
-
return
|
|
29682
|
+
return _context1.a(2);
|
|
29268
29683
|
case 2:
|
|
29269
|
-
|
|
29684
|
+
_context1.p = 2;
|
|
29270
29685
|
this._wakeLockRequesting = true;
|
|
29271
29686
|
// Request wake lock (screen type keeps screen on)
|
|
29272
|
-
|
|
29687
|
+
_context1.n = 3;
|
|
29273
29688
|
return navigator.wakeLock.request('screen');
|
|
29274
29689
|
case 3:
|
|
29275
|
-
this.wakeLock =
|
|
29690
|
+
this.wakeLock = _context1.v;
|
|
29276
29691
|
console.log('📱 VoiceSDK v2: Screen wake lock activated - screen will stay on during call');
|
|
29277
29692
|
|
|
29278
29693
|
// Handle wake lock release (e.g., user switches tabs, locks device)
|
|
@@ -29280,23 +29695,23 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29280
29695
|
console.log('📱 VoiceSDK v2: Wake lock released by system');
|
|
29281
29696
|
_this9.wakeLock = null;
|
|
29282
29697
|
});
|
|
29283
|
-
|
|
29698
|
+
_context1.n = 5;
|
|
29284
29699
|
break;
|
|
29285
29700
|
case 4:
|
|
29286
|
-
|
|
29287
|
-
|
|
29701
|
+
_context1.p = 4;
|
|
29702
|
+
_t0 = _context1.v;
|
|
29288
29703
|
// Wake lock request failed (e.g., permission denied, battery saver mode)
|
|
29289
|
-
console.warn('📱 VoiceSDK v2: Failed to request wake lock:',
|
|
29704
|
+
console.warn('📱 VoiceSDK v2: Failed to request wake lock:', _t0.message);
|
|
29290
29705
|
this.wakeLock = null;
|
|
29291
29706
|
// Don't throw - this is a nice-to-have feature, not critical
|
|
29292
29707
|
case 5:
|
|
29293
|
-
|
|
29708
|
+
_context1.p = 5;
|
|
29294
29709
|
this._wakeLockRequesting = false;
|
|
29295
|
-
return
|
|
29710
|
+
return _context1.f(5);
|
|
29296
29711
|
case 6:
|
|
29297
|
-
return
|
|
29712
|
+
return _context1.a(2);
|
|
29298
29713
|
}
|
|
29299
|
-
},
|
|
29714
|
+
}, _callee1, this, [[2, 4, 5, 6]]);
|
|
29300
29715
|
}));
|
|
29301
29716
|
function _requestWakeLock() {
|
|
29302
29717
|
return _requestWakeLock2.apply(this, arguments);
|
|
@@ -29311,34 +29726,34 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29311
29726
|
}, {
|
|
29312
29727
|
key: "_releaseWakeLock",
|
|
29313
29728
|
value: (function () {
|
|
29314
|
-
var _releaseWakeLock2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29315
|
-
var
|
|
29316
|
-
return _regenerator().w(function (
|
|
29317
|
-
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) {
|
|
29318
29733
|
case 0:
|
|
29319
29734
|
if (!(this.wakeLock === null)) {
|
|
29320
|
-
|
|
29735
|
+
_context10.n = 1;
|
|
29321
29736
|
break;
|
|
29322
29737
|
}
|
|
29323
|
-
return
|
|
29738
|
+
return _context10.a(2);
|
|
29324
29739
|
case 1:
|
|
29325
|
-
|
|
29326
|
-
|
|
29740
|
+
_context10.p = 1;
|
|
29741
|
+
_context10.n = 2;
|
|
29327
29742
|
return this.wakeLock.release();
|
|
29328
29743
|
case 2:
|
|
29329
29744
|
this.wakeLock = null;
|
|
29330
29745
|
console.log('📱 VoiceSDK v2: Screen wake lock released');
|
|
29331
|
-
|
|
29746
|
+
_context10.n = 4;
|
|
29332
29747
|
break;
|
|
29333
29748
|
case 3:
|
|
29334
|
-
|
|
29335
|
-
|
|
29336
|
-
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);
|
|
29337
29752
|
this.wakeLock = null;
|
|
29338
29753
|
case 4:
|
|
29339
|
-
return
|
|
29754
|
+
return _context10.a(2);
|
|
29340
29755
|
}
|
|
29341
|
-
},
|
|
29756
|
+
}, _callee10, this, [[1, 3]]);
|
|
29342
29757
|
}));
|
|
29343
29758
|
function _releaseWakeLock() {
|
|
29344
29759
|
return _releaseWakeLock2.apply(this, arguments);
|
|
@@ -29362,21 +29777,21 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
|
|
|
29362
29777
|
}, {
|
|
29363
29778
|
key: "handleBargeIn",
|
|
29364
29779
|
value: (function () {
|
|
29365
|
-
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function
|
|
29366
|
-
return _regenerator().w(function (
|
|
29367
|
-
while (1) switch (
|
|
29780
|
+
var _handleBargeIn = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
|
|
29781
|
+
return _regenerator().w(function (_context11) {
|
|
29782
|
+
while (1) switch (_context11.n) {
|
|
29368
29783
|
case 0:
|
|
29369
29784
|
this.stopAudioPlayback();
|
|
29370
29785
|
if (this.isRecording) {
|
|
29371
|
-
|
|
29786
|
+
_context11.n = 1;
|
|
29372
29787
|
break;
|
|
29373
29788
|
}
|
|
29374
|
-
|
|
29789
|
+
_context11.n = 1;
|
|
29375
29790
|
return this.startRecording();
|
|
29376
29791
|
case 1:
|
|
29377
|
-
return
|
|
29792
|
+
return _context11.a(2);
|
|
29378
29793
|
}
|
|
29379
|
-
},
|
|
29794
|
+
}, _callee11, this);
|
|
29380
29795
|
}));
|
|
29381
29796
|
function handleBargeIn() {
|
|
29382
29797
|
return _handleBargeIn.apply(this, arguments);
|
|
@@ -32289,10 +32704,17 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32289
32704
|
this._flavorObj = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
32290
32705
|
if (this._flavorObj && this._flavorObj.type) {
|
|
32291
32706
|
this._initFlavor(this._flavorObj.type);
|
|
32292
|
-
|
|
32293
|
-
|
|
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.)
|
|
32294
32710
|
console.error('[TTPChatWidget] flavor object is set but missing required "type" field. Widget will run in vanilla mode.');
|
|
32295
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();
|
|
32296
32718
|
}
|
|
32297
32719
|
|
|
32298
32720
|
/**
|
|
@@ -32708,7 +33130,11 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
32708
33130
|
offset: positionConfig.offset || {
|
|
32709
33131
|
x: 20,
|
|
32710
33132
|
y: 20
|
|
32711
|
-
}
|
|
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
|
|
32712
33138
|
}, _typeof(userConfig.position) === 'object' ? userConfig.position : {}),
|
|
32713
33139
|
// Button Configuration
|
|
32714
33140
|
button: _objectSpread({
|
|
@@ -33344,6 +33770,125 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33344
33770
|
var footer = (_root$querySelector = root.querySelector) === null || _root$querySelector === void 0 ? void 0 : _root$querySelector.call(root, '.ttp-footer');
|
|
33345
33771
|
if (footer) footer.style.display = visible ? '' : 'none';
|
|
33346
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
|
+
}
|
|
33347
33892
|
}, {
|
|
33348
33893
|
key: "generatePositionStyles",
|
|
33349
33894
|
value: function generatePositionStyles() {
|
|
@@ -33475,13 +34020,14 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33475
34020
|
var callActivePanelBg = callSurfaceGradient;
|
|
33476
34021
|
var voiceIdleVisibleSelector = '#voiceInterface.active #voiceIdleState:not([style*="display: none"]):not([style*="display:none"])';
|
|
33477
34022
|
var voiceActiveVisibleSelector = '#voiceInterface.active #voiceActiveState:not([style*="display: none"]):not([style*="display:none"])';
|
|
33478
|
-
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 ");
|
|
33479
34024
|
}
|
|
33480
34025
|
}, {
|
|
33481
34026
|
key: "setupWidgetEvents",
|
|
33482
34027
|
value: function setupWidgetEvents() {
|
|
33483
|
-
var
|
|
33484
|
-
_this$config$behavior8
|
|
34028
|
+
var _this9 = this,
|
|
34029
|
+
_this$config$behavior8,
|
|
34030
|
+
_this$config$position5;
|
|
33485
34031
|
if (!this.shadowRoot) return;
|
|
33486
34032
|
|
|
33487
34033
|
// Setup prompt animation visibility and interactions
|
|
@@ -33492,16 +34038,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33492
34038
|
if (launcherBtn) {
|
|
33493
34039
|
launcherBtn.onclick = function (e) {
|
|
33494
34040
|
e.stopPropagation();
|
|
33495
|
-
|
|
33496
|
-
|
|
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();
|
|
33497
34045
|
}
|
|
33498
|
-
|
|
34046
|
+
_this9.togglePanel();
|
|
33499
34047
|
};
|
|
33500
34048
|
}
|
|
33501
34049
|
var closeBtn = this.shadowRoot.getElementById('closeBtn');
|
|
33502
34050
|
if (closeBtn) {
|
|
33503
34051
|
closeBtn.onclick = function () {
|
|
33504
|
-
|
|
34052
|
+
_this9._doTogglePanel();
|
|
33505
34053
|
};
|
|
33506
34054
|
}
|
|
33507
34055
|
|
|
@@ -33509,31 +34057,41 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33509
34057
|
var closeIdle = this.shadowRoot.getElementById('ttpCloseIdle');
|
|
33510
34058
|
if (closeIdle) {
|
|
33511
34059
|
closeIdle.onclick = function () {
|
|
33512
|
-
return
|
|
34060
|
+
return _this9._doTogglePanel();
|
|
33513
34061
|
};
|
|
33514
34062
|
}
|
|
33515
34063
|
var closeActive = this.shadowRoot.getElementById('ttpCloseActive');
|
|
33516
34064
|
if (closeActive) {
|
|
33517
34065
|
closeActive.onclick = function () {
|
|
33518
|
-
return
|
|
34066
|
+
return _this9._doTogglePanel();
|
|
33519
34067
|
};
|
|
33520
34068
|
}
|
|
33521
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
|
+
|
|
33522
34080
|
// "Send a Message" button in idle view → switch to text interface
|
|
33523
34081
|
var startTextBtn = this.shadowRoot.getElementById('startTextBtn');
|
|
33524
34082
|
if (startTextBtn) {
|
|
33525
34083
|
startTextBtn.onclick = function () {
|
|
33526
|
-
return
|
|
34084
|
+
return _this9.showText();
|
|
33527
34085
|
};
|
|
33528
34086
|
}
|
|
33529
34087
|
var textUnifiedBackBtn = this.shadowRoot.getElementById('textUnifiedBackBtn');
|
|
33530
34088
|
if (textUnifiedBackBtn) {
|
|
33531
34089
|
textUnifiedBackBtn.onclick = function () {
|
|
33532
|
-
var
|
|
33533
|
-
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';
|
|
33534
34092
|
if (widgetMode !== 'unified') return;
|
|
33535
|
-
|
|
33536
|
-
|
|
34093
|
+
_this9.showLanding();
|
|
34094
|
+
_this9._openMobileCallTextLanding();
|
|
33537
34095
|
};
|
|
33538
34096
|
}
|
|
33539
34097
|
|
|
@@ -33563,30 +34121,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33563
34121
|
// Setup back button handler
|
|
33564
34122
|
if (backBtn) {
|
|
33565
34123
|
backBtn.onclick = function () {
|
|
33566
|
-
var
|
|
34124
|
+
var _this9$voiceInterface, _this9$voiceInterface3;
|
|
33567
34125
|
// Check if we're showing a domain error — clear it and return to voice hero
|
|
33568
|
-
if ((
|
|
33569
|
-
var
|
|
34126
|
+
if ((_this9$voiceInterface = _this9.voiceInterface) !== null && _this9$voiceInterface !== void 0 && _this9$voiceInterface.isShowingDomainError) {
|
|
34127
|
+
var _this9$voiceInterface2;
|
|
33570
34128
|
console.log('🔙 Back button clicked - clearing domain error and returning to voice hero');
|
|
33571
34129
|
// Clear the domain error flag
|
|
33572
|
-
|
|
34130
|
+
_this9.voiceInterface.isShowingDomainError = false;
|
|
33573
34131
|
// Reset the connecting state (this will restore normal UI)
|
|
33574
|
-
if ((
|
|
33575
|
-
|
|
34132
|
+
if ((_this9$voiceInterface2 = _this9.voiceInterface) !== null && _this9$voiceInterface2 !== void 0 && _this9$voiceInterface2.resetConnectingState) {
|
|
34133
|
+
_this9.voiceInterface.resetConnectingState();
|
|
33576
34134
|
}
|
|
33577
|
-
|
|
33578
|
-
|
|
34135
|
+
_this9.showLanding();
|
|
34136
|
+
_this9._openMobileCallTextLanding();
|
|
33579
34137
|
return;
|
|
33580
34138
|
}
|
|
33581
|
-
if ((
|
|
34139
|
+
if ((_this9$voiceInterface3 = _this9.voiceInterface) !== null && _this9$voiceInterface3 !== void 0 && _this9$voiceInterface3.isActive) {
|
|
33582
34140
|
// If call is active, show message inside widget instead of modal
|
|
33583
|
-
|
|
34141
|
+
_this9.showBackButtonWarning();
|
|
33584
34142
|
} else if (window.innerWidth <= 768) {
|
|
33585
|
-
|
|
33586
|
-
|
|
34143
|
+
_this9.showLanding();
|
|
34144
|
+
_this9._openMobileCallTextLanding();
|
|
33587
34145
|
} else {
|
|
33588
34146
|
// Desktop: return to voice hero (unified home)
|
|
33589
|
-
|
|
34147
|
+
_this9.showLanding();
|
|
33590
34148
|
}
|
|
33591
34149
|
};
|
|
33592
34150
|
}
|
|
@@ -33629,7 +34187,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33629
34187
|
// Setup header button handlers
|
|
33630
34188
|
if (newChatBtn) {
|
|
33631
34189
|
newChatBtn.onclick = function () {
|
|
33632
|
-
return
|
|
34190
|
+
return _this9.textInterface.startNewChat();
|
|
33633
34191
|
};
|
|
33634
34192
|
// Hide new chat on unified home (voice hero) initially
|
|
33635
34193
|
if (isUnified && this.currentView !== 'text') {
|
|
@@ -33640,11 +34198,328 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33640
34198
|
// Mobile floating button & landing overlay
|
|
33641
34199
|
this.setupMobileWidgetEvents();
|
|
33642
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
|
+
|
|
33643
34208
|
// Keyboard navigation
|
|
33644
34209
|
if (this.config.accessibility.keyboardNavigation) {
|
|
33645
34210
|
this.setupKeyboardNavigation();
|
|
33646
34211
|
}
|
|
33647
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
|
+
}
|
|
33648
34523
|
}, {
|
|
33649
34524
|
key: "startNewChat",
|
|
33650
34525
|
value: function startNewChat() {
|
|
@@ -33691,9 +34566,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33691
34566
|
}, {
|
|
33692
34567
|
key: "_isDomainErrorVisible",
|
|
33693
34568
|
value: function _isDomainErrorVisible() {
|
|
33694
|
-
var _this$
|
|
33695
|
-
if ((_this$
|
|
33696
|
-
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');
|
|
33697
34572
|
return idleState && ((_idleState$dataset = idleState.dataset) === null || _idleState$dataset === void 0 ? void 0 : _idleState$dataset.domainError) === 'true';
|
|
33698
34573
|
}
|
|
33699
34574
|
}, {
|
|
@@ -33721,7 +34596,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33721
34596
|
}, {
|
|
33722
34597
|
key: "_openMobileCallTextLanding",
|
|
33723
34598
|
value: function _openMobileCallTextLanding() {
|
|
33724
|
-
var
|
|
34599
|
+
var _this12 = this;
|
|
33725
34600
|
if (!this.shadowRoot || window.innerWidth > 768) return;
|
|
33726
34601
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33727
34602
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33732,30 +34607,30 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33732
34607
|
// "Back" button: composedPath includes the panel but not #ttpMobileLanding, so it treated
|
|
33733
34608
|
// the click as "outside" and closed the landing immediately (user only saw the FAB again).
|
|
33734
34609
|
var open = function open() {
|
|
33735
|
-
if (!
|
|
33736
|
-
var panel =
|
|
34610
|
+
if (!_this12.shadowRoot || window.innerWidth > 768) return;
|
|
34611
|
+
var panel = _this12.shadowRoot.getElementById('text-chat-panel');
|
|
33737
34612
|
if (panel) {
|
|
33738
34613
|
panel.classList.remove('open');
|
|
33739
|
-
|
|
34614
|
+
_this12.isOpen = false;
|
|
33740
34615
|
}
|
|
33741
|
-
if (
|
|
33742
|
-
|
|
34616
|
+
if (_this12.config.promptAnimation.hideAfterClick) {
|
|
34617
|
+
_this12.hidePrompt();
|
|
33743
34618
|
}
|
|
33744
|
-
var errorBanner =
|
|
34619
|
+
var errorBanner = _this12.shadowRoot.getElementById('ttpMobileLandingError');
|
|
33745
34620
|
if (errorBanner) errorBanner.style.display = 'none';
|
|
33746
|
-
var fab =
|
|
33747
|
-
var landing =
|
|
34621
|
+
var fab = _this12.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
34622
|
+
var landing = _this12.shadowRoot.getElementById('ttpMobileLanding');
|
|
33748
34623
|
if (!fab || !landing) return;
|
|
33749
34624
|
fab.style.display = 'none';
|
|
33750
34625
|
landing.classList.add('active');
|
|
33751
|
-
|
|
34626
|
+
_this12.isMobileLandingOpen = true;
|
|
33752
34627
|
};
|
|
33753
34628
|
queueMicrotask(open);
|
|
33754
34629
|
}
|
|
33755
34630
|
}, {
|
|
33756
34631
|
key: "setupMobileWidgetEvents",
|
|
33757
34632
|
value: function setupMobileWidgetEvents() {
|
|
33758
|
-
var
|
|
34633
|
+
var _this13 = this;
|
|
33759
34634
|
if (!this.shadowRoot) return;
|
|
33760
34635
|
var mobileFab = this.shadowRoot.querySelector('.ttp-mobile-fab');
|
|
33761
34636
|
var mobileLanding = this.shadowRoot.getElementById('ttpMobileLanding');
|
|
@@ -33763,10 +34638,12 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33763
34638
|
var closeMobileLanding = function closeMobileLanding() {
|
|
33764
34639
|
mobileLanding.classList.remove('active');
|
|
33765
34640
|
mobileFab.style.display = '';
|
|
33766
|
-
|
|
34641
|
+
_this13.isMobileLandingOpen = false;
|
|
33767
34642
|
};
|
|
33768
34643
|
mobileFab.onclick = function () {
|
|
33769
|
-
|
|
34644
|
+
// A drag just ended — don't open the landing on the trailing click.
|
|
34645
|
+
if (_this13._suppressLauncherClick) return;
|
|
34646
|
+
_this13._openMobileCallTextLanding();
|
|
33770
34647
|
};
|
|
33771
34648
|
var mobileClose = mobileLanding.querySelector('.ttp-mobile-landing__close');
|
|
33772
34649
|
if (mobileClose) {
|
|
@@ -33776,18 +34653,18 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33776
34653
|
if (mobileCallBtn) {
|
|
33777
34654
|
mobileCallBtn.onclick = function () {
|
|
33778
34655
|
closeMobileLanding();
|
|
33779
|
-
var panel =
|
|
34656
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33780
34657
|
if (panel) {
|
|
33781
34658
|
panel.style.removeProperty('display');
|
|
33782
34659
|
panel.classList.add('open');
|
|
33783
|
-
|
|
34660
|
+
_this13.isOpen = true;
|
|
33784
34661
|
}
|
|
33785
34662
|
mobileFab.style.display = 'none';
|
|
33786
|
-
|
|
34663
|
+
_this13.showVoice();
|
|
33787
34664
|
// Landing already chose "Voice call" — start the call (mic permission / pre-prompt) instead of
|
|
33788
34665
|
// leaving users on a second "Start Call" tap that feels broken.
|
|
33789
34666
|
queueMicrotask(function () {
|
|
33790
|
-
|
|
34667
|
+
_this13.startVoiceCall().catch(function (err) {
|
|
33791
34668
|
console.error('[TTPChatWidget] Mobile landing voice start failed:', err);
|
|
33792
34669
|
});
|
|
33793
34670
|
});
|
|
@@ -33797,20 +34674,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33797
34674
|
if (mobileChatBtn) {
|
|
33798
34675
|
mobileChatBtn.onclick = function () {
|
|
33799
34676
|
closeMobileLanding();
|
|
33800
|
-
var panel =
|
|
34677
|
+
var panel = _this13.shadowRoot.getElementById('text-chat-panel');
|
|
33801
34678
|
if (panel) {
|
|
33802
34679
|
panel.style.removeProperty('display');
|
|
33803
34680
|
panel.classList.add('open');
|
|
33804
|
-
|
|
34681
|
+
_this13.isOpen = true;
|
|
33805
34682
|
}
|
|
33806
34683
|
mobileFab.style.display = 'none';
|
|
33807
|
-
|
|
34684
|
+
_this13.showText();
|
|
33808
34685
|
};
|
|
33809
34686
|
}
|
|
33810
34687
|
|
|
33811
34688
|
// Close mobile landing on outside click
|
|
33812
34689
|
document.addEventListener('click', function (e) {
|
|
33813
|
-
if (!
|
|
34690
|
+
if (!_this13.isMobileLandingOpen) return;
|
|
33814
34691
|
var path = e.composedPath();
|
|
33815
34692
|
if (!path.includes(mobileLanding) && !path.includes(mobileFab)) {
|
|
33816
34693
|
closeMobileLanding();
|
|
@@ -33819,7 +34696,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33819
34696
|
|
|
33820
34697
|
// Close mobile landing on Escape
|
|
33821
34698
|
document.addEventListener('keydown', function (e) {
|
|
33822
|
-
if (e.key === 'Escape' &&
|
|
34699
|
+
if (e.key === 'Escape' && _this13.isMobileLandingOpen) {
|
|
33823
34700
|
closeMobileLanding();
|
|
33824
34701
|
}
|
|
33825
34702
|
});
|
|
@@ -33835,19 +34712,19 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33835
34712
|
_prevIsMobile = nowMobile;
|
|
33836
34713
|
if (nowMobile) {
|
|
33837
34714
|
// Switched desktop → mobile: close desktop panel so only mobile FAB shows
|
|
33838
|
-
if (
|
|
33839
|
-
var
|
|
33840
|
-
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');
|
|
33841
34718
|
if (panel) {
|
|
33842
34719
|
panel.classList.remove('open');
|
|
33843
|
-
|
|
34720
|
+
_this13.isOpen = false;
|
|
33844
34721
|
}
|
|
33845
|
-
var pill = (
|
|
34722
|
+
var pill = (_this13$shadowRoot2 = _this13.shadowRoot) === null || _this13$shadowRoot2 === void 0 ? void 0 : _this13$shadowRoot2.getElementById('text-chat-button');
|
|
33846
34723
|
if (pill) pill.classList.remove('open');
|
|
33847
34724
|
}
|
|
33848
34725
|
} else {
|
|
33849
34726
|
// Switched mobile → desktop: close mobile landing/FAB so only desktop pill shows
|
|
33850
|
-
if (
|
|
34727
|
+
if (_this13.isMobileLandingOpen) {
|
|
33851
34728
|
closeMobileLanding();
|
|
33852
34729
|
}
|
|
33853
34730
|
// Ensure mobile FAB is reset to CSS-controlled state (media query hides it on desktop)
|
|
@@ -33859,10 +34736,10 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33859
34736
|
}, {
|
|
33860
34737
|
key: "setupKeyboardNavigation",
|
|
33861
34738
|
value: function setupKeyboardNavigation() {
|
|
33862
|
-
var
|
|
34739
|
+
var _this14 = this;
|
|
33863
34740
|
document.addEventListener('keydown', function (e) {
|
|
33864
|
-
if (e.key === 'Escape' &&
|
|
33865
|
-
|
|
34741
|
+
if (e.key === 'Escape' && _this14.isOpen) {
|
|
34742
|
+
_this14.togglePanel();
|
|
33866
34743
|
}
|
|
33867
34744
|
});
|
|
33868
34745
|
}
|
|
@@ -33873,7 +34750,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33873
34750
|
}, {
|
|
33874
34751
|
key: "setupPromptAnimation",
|
|
33875
34752
|
value: function setupPromptAnimation() {
|
|
33876
|
-
var
|
|
34753
|
+
var _this15 = this;
|
|
33877
34754
|
if (!this.shadowRoot) return;
|
|
33878
34755
|
var promptConfig = this.config.promptAnimation || {};
|
|
33879
34756
|
// Default to disabled if not specified (enabled === true means explicitly enabled)
|
|
@@ -33903,7 +34780,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33903
34780
|
// Auto-hide after configured seconds (only if widget is closed)
|
|
33904
34781
|
if (!this.isOpen && promptConfig.hideAfterSeconds !== null && promptConfig.hideAfterSeconds > 0) {
|
|
33905
34782
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
33906
|
-
|
|
34783
|
+
_this15.hidePrompt();
|
|
33907
34784
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
33908
34785
|
}
|
|
33909
34786
|
|
|
@@ -33915,7 +34792,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33915
34792
|
// Wrap the callback to also hide pulse rings
|
|
33916
34793
|
this.config.onConversationStart = function () {
|
|
33917
34794
|
// Hide pulse rings when call starts
|
|
33918
|
-
var pulseRings =
|
|
34795
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33919
34796
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33920
34797
|
|
|
33921
34798
|
// Call original callback if it exists
|
|
@@ -33927,7 +34804,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33927
34804
|
// Also listen to recordingStarted event from SDK if available
|
|
33928
34805
|
if (this.voiceInterface.sdk.voiceSDK) {
|
|
33929
34806
|
this.voiceInterface.sdk.voiceSDK.on('recordingStarted', function () {
|
|
33930
|
-
var pulseRings =
|
|
34807
|
+
var pulseRings = _this15.shadowRoot.getElementById('prompt-pulse-rings');
|
|
33931
34808
|
if (pulseRings) pulseRings.style.display = 'none';
|
|
33932
34809
|
});
|
|
33933
34810
|
}
|
|
@@ -33975,7 +34852,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33975
34852
|
}, {
|
|
33976
34853
|
key: "showPrompt",
|
|
33977
34854
|
value: function showPrompt() {
|
|
33978
|
-
var
|
|
34855
|
+
var _this16 = this;
|
|
33979
34856
|
if (!this.shadowRoot) return;
|
|
33980
34857
|
var promptConfig = this.config.promptAnimation || {};
|
|
33981
34858
|
// Default to enabled if not specified
|
|
@@ -33995,8 +34872,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
33995
34872
|
// Function to actually show the elements
|
|
33996
34873
|
var doShow = function doShow() {
|
|
33997
34874
|
// Show prompt bubble (check both shadow root and document for compatibility)
|
|
33998
|
-
var promptBubble =
|
|
33999
|
-
if (!promptBubble &&
|
|
34875
|
+
var promptBubble = _this16.shadowRoot.getElementById('prompt-bubble');
|
|
34876
|
+
if (!promptBubble && _this16.shadowRoot !== document) {
|
|
34000
34877
|
promptBubble = document.getElementById('prompt-bubble');
|
|
34001
34878
|
}
|
|
34002
34879
|
if (promptBubble) {
|
|
@@ -34010,8 +34887,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34010
34887
|
|
|
34011
34888
|
// Show pulse rings if enabled
|
|
34012
34889
|
if (promptConfig.showPulseRings !== false) {
|
|
34013
|
-
var _pulseRings =
|
|
34014
|
-
if (!_pulseRings &&
|
|
34890
|
+
var _pulseRings = _this16.shadowRoot.getElementById('prompt-pulse-rings');
|
|
34891
|
+
if (!_pulseRings && _this16.shadowRoot !== document) {
|
|
34015
34892
|
_pulseRings = document.getElementById('prompt-pulse-rings');
|
|
34016
34893
|
}
|
|
34017
34894
|
if (_pulseRings) {
|
|
@@ -34048,7 +34925,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34048
34925
|
}
|
|
34049
34926
|
// Start new timer
|
|
34050
34927
|
this.promptAutoHideTimer = setTimeout(function () {
|
|
34051
|
-
|
|
34928
|
+
_this16.hidePrompt();
|
|
34052
34929
|
}, promptConfig.hideAfterSeconds * 1000);
|
|
34053
34930
|
}
|
|
34054
34931
|
}
|
|
@@ -34064,14 +34941,23 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34064
34941
|
}, {
|
|
34065
34942
|
key: "_doTogglePanel",
|
|
34066
34943
|
value: function _doTogglePanel() {
|
|
34067
|
-
var
|
|
34944
|
+
var _this17 = this;
|
|
34068
34945
|
if (!this.shadowRoot) return;
|
|
34069
34946
|
this.isOpen = !this.isOpen;
|
|
34070
34947
|
var panel = this.shadowRoot.getElementById('text-chat-panel');
|
|
34071
34948
|
if (panel) {
|
|
34072
34949
|
panel.classList.toggle('open');
|
|
34073
34950
|
if (this.isOpen) {
|
|
34951
|
+
var _this$config$position8;
|
|
34074
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
|
+
}
|
|
34075
34961
|
}
|
|
34076
34962
|
}
|
|
34077
34963
|
|
|
@@ -34086,7 +34972,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34086
34972
|
// Panel is opening - hide prompt
|
|
34087
34973
|
this.hidePrompt();
|
|
34088
34974
|
setTimeout(function () {
|
|
34089
|
-
var input =
|
|
34975
|
+
var input = _this17.shadowRoot.getElementById('messageInput');
|
|
34090
34976
|
if (input) input.focus();
|
|
34091
34977
|
}, 100);
|
|
34092
34978
|
} else {
|
|
@@ -34098,13 +34984,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34098
34984
|
// Panel is closing - show prompt (if enabled)
|
|
34099
34985
|
this.showPrompt();
|
|
34100
34986
|
setTimeout(function () {
|
|
34101
|
-
var
|
|
34102
|
-
var promptBubble =
|
|
34987
|
+
var _this17$config$prompt;
|
|
34988
|
+
var promptBubble = _this17.shadowRoot.getElementById('prompt-bubble');
|
|
34103
34989
|
if (promptBubble && promptBubble.style.display === 'none') {
|
|
34104
34990
|
promptBubble.style.display = 'block';
|
|
34105
34991
|
}
|
|
34106
|
-
var pulseRings =
|
|
34107
|
-
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) {
|
|
34108
34994
|
if (pulseRings.style.display === 'none') {
|
|
34109
34995
|
pulseRings.style.display = 'block';
|
|
34110
34996
|
}
|
|
@@ -34296,8 +35182,8 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34296
35182
|
}, {
|
|
34297
35183
|
key: "showBackButtonWarning",
|
|
34298
35184
|
value: function showBackButtonWarning() {
|
|
34299
|
-
var _this$
|
|
34300
|
-
if (!((_this$
|
|
35185
|
+
var _this$voiceInterface6, _this$voiceInterface$;
|
|
35186
|
+
if (!((_this$voiceInterface6 = this.voiceInterface) !== null && _this$voiceInterface6 !== void 0 && _this$voiceInterface6.isActive)) return;
|
|
34301
35187
|
|
|
34302
35188
|
// Show warning message in the voice interface
|
|
34303
35189
|
if ((_this$voiceInterface$ = this.voiceInterface.desktop) !== null && _this$voiceInterface$ !== void 0 && _this$voiceInterface$.showBackButtonWarning) {
|
|
@@ -34378,7 +35264,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34378
35264
|
_this$config$voice0,
|
|
34379
35265
|
_this$config$voice1,
|
|
34380
35266
|
_this$config$voice10,
|
|
34381
|
-
|
|
35267
|
+
_this18 = this;
|
|
34382
35268
|
// Deep merge nested objects
|
|
34383
35269
|
var mergedConfig = _objectSpread({}, this.config);
|
|
34384
35270
|
|
|
@@ -34596,20 +35482,20 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34596
35482
|
outputBitDepth: ((_this$config$voice10 = this.config.voice) === null || _this$config$voice10 === void 0 ? void 0 : _this$config$voice10.outputBitDepth) || 16,
|
|
34597
35483
|
desktopMinimizedEcommerceStripUi: desktopMinimizedEcommerceStripUi,
|
|
34598
35484
|
onDesktopMinimizedStripCallStart: desktopMinimizedEcommerceStripUi ? function () {
|
|
34599
|
-
var
|
|
34600
|
-
(
|
|
34601
|
-
if (
|
|
34602
|
-
|
|
34603
|
-
|
|
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);
|
|
34604
35490
|
} : undefined,
|
|
34605
35491
|
onDesktopMinimizedStripLauncherRestore: desktopMinimizedEcommerceStripUi ? function () {
|
|
34606
|
-
return
|
|
35492
|
+
return _this18._restoreDesktopEcommerceStripChrome();
|
|
34607
35493
|
} : undefined,
|
|
34608
35494
|
// Pass event callbacks to voice interface (forward only; panel is not auto-minimized on call start)
|
|
34609
35495
|
onConversationStart: function onConversationStart() {
|
|
34610
|
-
if (typeof
|
|
34611
|
-
var
|
|
34612
|
-
(
|
|
35496
|
+
if (typeof _this18.config.onConversationStart === 'function') {
|
|
35497
|
+
var _this18$config;
|
|
35498
|
+
(_this18$config = _this18.config).onConversationStart.apply(_this18$config, arguments);
|
|
34613
35499
|
}
|
|
34614
35500
|
},
|
|
34615
35501
|
onConversationEnd: this.config.onConversationEnd,
|
|
@@ -34618,48 +35504,48 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34618
35504
|
onAudioStoppedPlaying: this.config.onAudioStoppedPlaying,
|
|
34619
35505
|
onSubtitleDisplay: this.config.onSubtitleDisplay,
|
|
34620
35506
|
onCallEnd: function onCallEnd() {
|
|
34621
|
-
var
|
|
34622
|
-
if (
|
|
34623
|
-
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';
|
|
34624
35510
|
if (widgetMode === 'unified') {
|
|
34625
35511
|
if (window.innerWidth <= 768) {
|
|
34626
|
-
var
|
|
34627
|
-
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');
|
|
34628
35514
|
if (panel) {
|
|
34629
35515
|
panel.classList.remove('open');
|
|
34630
|
-
|
|
35516
|
+
_this18.isOpen = false;
|
|
34631
35517
|
}
|
|
34632
|
-
var fab = (
|
|
35518
|
+
var fab = (_this18$shadowRoot2 = _this18.shadowRoot) === null || _this18$shadowRoot2 === void 0 ? void 0 : _this18$shadowRoot2.querySelector('.ttp-mobile-fab');
|
|
34633
35519
|
if (fab) fab.style.display = '';
|
|
34634
35520
|
}
|
|
34635
|
-
|
|
35521
|
+
_this18.showLanding();
|
|
34636
35522
|
}
|
|
34637
35523
|
},
|
|
34638
35524
|
onShowVoice: function onShowVoice() {
|
|
34639
|
-
|
|
35525
|
+
_this18.showVoice();
|
|
34640
35526
|
},
|
|
34641
35527
|
onShowLanding: function onShowLanding() {
|
|
34642
|
-
|
|
35528
|
+
_this18.showLanding();
|
|
34643
35529
|
},
|
|
34644
35530
|
onDisclaimerDeclined: function onDisclaimerDeclined() {
|
|
34645
|
-
var
|
|
34646
|
-
if (
|
|
34647
|
-
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';
|
|
34648
35534
|
if (widgetMode === 'voice-only') {
|
|
34649
|
-
|
|
35535
|
+
_this18.showVoice();
|
|
34650
35536
|
return;
|
|
34651
35537
|
}
|
|
34652
35538
|
if (widgetMode !== 'unified') return;
|
|
34653
35539
|
if (window.innerWidth <= 768) {
|
|
34654
|
-
var
|
|
34655
|
-
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');
|
|
34656
35542
|
if (panel) {
|
|
34657
35543
|
panel.classList.remove('open');
|
|
34658
|
-
|
|
35544
|
+
_this18.isOpen = false;
|
|
34659
35545
|
}
|
|
34660
|
-
|
|
35546
|
+
_this18._openMobileCallTextLanding();
|
|
34661
35547
|
} else {
|
|
34662
|
-
|
|
35548
|
+
_this18.showLanding();
|
|
34663
35549
|
}
|
|
34664
35550
|
},
|
|
34665
35551
|
direction: this.getEffectiveTextDirection()
|
|
@@ -34706,8 +35592,9 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34706
35592
|
}, {
|
|
34707
35593
|
key: "_initEcommerceVoiceStrip",
|
|
34708
35594
|
value: function _initEcommerceVoiceStrip() {
|
|
34709
|
-
var
|
|
34710
|
-
_this$
|
|
35595
|
+
var _this19 = this,
|
|
35596
|
+
_this$config$position9,
|
|
35597
|
+
_this$voiceInterface7;
|
|
34711
35598
|
var flavor = this.config.flavor && _typeof(this.config.flavor) === 'object' ? this.config.flavor : null;
|
|
34712
35599
|
if (window.innerWidth <= 768) return;
|
|
34713
35600
|
if (!flavor || flavor.callView !== 'minimized') return;
|
|
@@ -34728,31 +35615,34 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34728
35615
|
endCallButtonColor: v.endCallButtonColor || '#ef4444'
|
|
34729
35616
|
},
|
|
34730
35617
|
getVoiceUiState: function getVoiceUiState() {
|
|
34731
|
-
var
|
|
35618
|
+
var _this19$voiceInterfac, _this19$voiceInterfac2, _this19$voiceInterfac3;
|
|
34732
35619
|
return {
|
|
34733
|
-
isMicMuted: !!((
|
|
34734
|
-
isPaused: !!((
|
|
34735
|
-
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)
|
|
34736
35623
|
};
|
|
34737
35624
|
},
|
|
35625
|
+
onAbout: function onAbout() {
|
|
35626
|
+
return _this19._openAboutModal();
|
|
35627
|
+
},
|
|
34738
35628
|
onHangup: function onHangup() {
|
|
34739
|
-
if (
|
|
35629
|
+
if (_this19.voiceInterface) _this19.voiceInterface.endVoiceCall();
|
|
34740
35630
|
},
|
|
34741
35631
|
onToggleMute: function onToggleMute() {
|
|
34742
|
-
if (
|
|
35632
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleMute();
|
|
34743
35633
|
strip.syncFromVoice();
|
|
34744
35634
|
},
|
|
34745
35635
|
onTogglePause: function onTogglePause() {
|
|
34746
|
-
if (
|
|
35636
|
+
if (_this19.voiceInterface) _this19.voiceInterface.togglePause();
|
|
34747
35637
|
strip.syncFromVoice();
|
|
34748
35638
|
},
|
|
34749
35639
|
onToggleSpeaker: function onToggleSpeaker() {
|
|
34750
|
-
if (
|
|
35640
|
+
if (_this19.voiceInterface) _this19.voiceInterface.toggleSpeaker();
|
|
34751
35641
|
strip.syncFromVoice();
|
|
34752
35642
|
},
|
|
34753
35643
|
onSendText: function onSendText(text) {
|
|
34754
|
-
var
|
|
34755
|
-
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;
|
|
34756
35646
|
if (voiceSDK && typeof voiceSDK.sendMessage === 'function') {
|
|
34757
35647
|
voiceSDK.sendMessage({
|
|
34758
35648
|
t: 'text_inject',
|
|
@@ -34763,8 +35653,13 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34763
35653
|
});
|
|
34764
35654
|
this._ecommerceVoiceStrip = strip;
|
|
34765
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
|
+
|
|
34766
35661
|
// Show strip when conversation starts
|
|
34767
|
-
var agentSDK = (_this$
|
|
35662
|
+
var agentSDK = (_this$voiceInterface7 = this.voiceInterface) === null || _this$voiceInterface7 === void 0 ? void 0 : _this$voiceInterface7.sdk;
|
|
34768
35663
|
if (agentSDK) {
|
|
34769
35664
|
var origConvStart = agentSDK.onConversationStart;
|
|
34770
35665
|
agentSDK.onConversationStart = function () {
|
|
@@ -34802,7 +35697,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34802
35697
|
var _this$voiceInterface$2;
|
|
34803
35698
|
var origOnCallEnd = this.voiceInterface.config.onCallEnd;
|
|
34804
35699
|
this.voiceInterface.config.onCallEnd = function () {
|
|
34805
|
-
|
|
35700
|
+
_this19._restoreDesktopEcommerceStripChrome();
|
|
34806
35701
|
if (typeof origOnCallEnd === 'function') origOnCallEnd();
|
|
34807
35702
|
};
|
|
34808
35703
|
|
|
@@ -34926,7 +35821,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34926
35821
|
key: "injectData",
|
|
34927
35822
|
value: (function () {
|
|
34928
35823
|
var _injectData = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(data) {
|
|
34929
|
-
var _this$
|
|
35824
|
+
var _this$voiceInterface8;
|
|
34930
35825
|
var options,
|
|
34931
35826
|
voiceSDK,
|
|
34932
35827
|
ack,
|
|
@@ -34951,7 +35846,7 @@ var TTPChatWidget = /*#__PURE__*/function () {
|
|
|
34951
35846
|
throw new Error('Voice call is not active');
|
|
34952
35847
|
case 2:
|
|
34953
35848
|
// Check if SDK is available
|
|
34954
|
-
voiceSDK = (_this$
|
|
35849
|
+
voiceSDK = (_this$voiceInterface8 = this.voiceInterface) === null || _this$voiceInterface8 === void 0 ? void 0 : _this$voiceInterface8.getVoiceSDK();
|
|
34955
35850
|
if (voiceSDK) {
|
|
34956
35851
|
_context6.n = 3;
|
|
34957
35852
|
break;
|
|
@@ -35216,7 +36111,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35216
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...';
|
|
35217
36112
|
var unifiedMode = ((_this$config$behavior = this.config.behavior) === null || _this$config$behavior === void 0 ? void 0 : _this$config$behavior.mode) === 'unified';
|
|
35218
36113
|
var backArrow = this.config.direction === 'rtl' ? '→' : '←';
|
|
35219
|
-
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>") : '';
|
|
35220
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>");
|
|
35221
36116
|
}
|
|
35222
36117
|
|
|
@@ -35348,7 +36243,7 @@ var TextInterface = /*#__PURE__*/function () {
|
|
|
35348
36243
|
|
|
35349
36244
|
// Add !important to display rules when not using Shadow DOM (to override theme CSS)
|
|
35350
36245
|
var important = this.config.useShadowDOM === false ? ' !important' : '';
|
|
35351
|
-
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 ");
|
|
35352
36247
|
}
|
|
35353
36248
|
|
|
35354
36249
|
/**
|
|
@@ -37426,6 +38321,7 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37426
38321
|
clearInterval(this.callTimerInterval);
|
|
37427
38322
|
this.callTimerInterval = null;
|
|
37428
38323
|
}
|
|
38324
|
+
this.callStartTime = null;
|
|
37429
38325
|
|
|
37430
38326
|
// Hide active state, show idle state first
|
|
37431
38327
|
activeState = this.shadowRoot.getElementById('voiceActiveState');
|
|
@@ -37594,6 +38490,10 @@ var VoiceInterface = /*#__PURE__*/function () {
|
|
|
37594
38490
|
clearInterval(this.callTimerInterval);
|
|
37595
38491
|
this.callTimerInterval = null;
|
|
37596
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;
|
|
37597
38497
|
|
|
37598
38498
|
// Clean up text inject timeouts and handlers (desktop)
|
|
37599
38499
|
if (this._textInjectTimeout) {
|
|
@@ -40341,6 +41241,21 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40341
41241
|
return this.voiceInterface.getTooltip(key);
|
|
40342
41242
|
}
|
|
40343
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
|
+
|
|
40344
41259
|
/**
|
|
40345
41260
|
* Generate HTML for voice interface.
|
|
40346
41261
|
* Automatically detects mobile vs desktop based on voiceInterface.isMobile
|
|
@@ -40371,7 +41286,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40371
41286
|
var transcriptPlaceholder = this.t('transcriptWillAppear') || '';
|
|
40372
41287
|
var transcriptDir = (0,_rtlText_js__WEBPACK_IMPORTED_MODULE_0__.dirForTranscriptSnippet)(transcriptPlaceholder, this.config);
|
|
40373
41288
|
var voiceInputDir = (0,_rtlText_js__WEBPACK_IMPORTED_MODULE_0__.dirForAssistantStreamingText)(this.config);
|
|
40374
|
-
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>");
|
|
40375
41290
|
}
|
|
40376
41291
|
|
|
40377
41292
|
/**
|
|
@@ -40388,7 +41303,7 @@ var Templates = /*#__PURE__*/function () {
|
|
|
40388
41303
|
var headerAvatarUrl = resolveIdleHeaderAvatarUrl(this.config);
|
|
40389
41304
|
var mobileAvatarInner = headerAvatarUrl ? "<img src=\"".concat(escapeHtmlAttr(headerAvatarUrl), "\" alt=\"\" class=\"voice-avatar-img\" />") : '🤖';
|
|
40390
41305
|
var mobileAvatarClass = headerAvatarUrl ? 'voice-avatar voice-avatar--image' : 'voice-avatar';
|
|
40391
|
-
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) {
|
|
40392
41307
|
return "<div class=\"mobile-waveform-bar\" data-index=\"".concat(i, "\"></div>");
|
|
40393
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>");
|
|
40394
41309
|
}
|
|
@@ -41233,7 +42148,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41233
42148
|
"typeMessage": "Type your message...",
|
|
41234
42149
|
"sendMessageAria": "Send message",
|
|
41235
42150
|
"domainNotValidated": "Domain not validated",
|
|
41236
|
-
"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"
|
|
41237
42156
|
},
|
|
41238
42157
|
"he": {
|
|
41239
42158
|
"landingTitle": "איך תרצה לתקשר?",
|
|
@@ -41266,7 +42185,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41266
42185
|
"typeMessage": "הקלד הודעה...",
|
|
41267
42186
|
"sendMessageAria": "שלח הודעה",
|
|
41268
42187
|
"domainNotValidated": "דומיין לא מאומת",
|
|
41269
|
-
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה."
|
|
42188
|
+
"domainErrorMessage": "דומיין זה לא ברשימת המורשים. אנא פנה למנהל המערכת כדי להוסיף את כתובת האתר שלך לרשימה.",
|
|
42189
|
+
"aboutTitle": "אודות",
|
|
42190
|
+
"aboutVersion": "גרסת SDK",
|
|
42191
|
+
"aboutConversationId": "מזהה שיחה אחרון",
|
|
42192
|
+
"aboutNoConversation": "אין שיחה עדיין"
|
|
41270
42193
|
},
|
|
41271
42194
|
"ar": {
|
|
41272
42195
|
"landingTitle": "كيف تريد التواصل؟",
|
|
@@ -41299,7 +42222,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41299
42222
|
"typeMessage": "اكتب رسالة...",
|
|
41300
42223
|
"sendMessageAria": "إرسال رسالة",
|
|
41301
42224
|
"domainNotValidated": "النطاق غير معتمد",
|
|
41302
|
-
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة."
|
|
42225
|
+
"domainErrorMessage": "هذا النطاق غير مسموح به. يرجى الاتصال بالمسؤول لإضافة عنوان موقع الويب الخاص بك إلى القائمة.",
|
|
42226
|
+
"aboutTitle": "حول",
|
|
42227
|
+
"aboutVersion": "إصدار SDK",
|
|
42228
|
+
"aboutConversationId": "معرّف آخر محادثة",
|
|
42229
|
+
"aboutNoConversation": "لا توجد محادثة بعد"
|
|
41303
42230
|
},
|
|
41304
42231
|
"ru": {
|
|
41305
42232
|
"landingTitle": "Как вы хотите общаться?",
|
|
@@ -41332,7 +42259,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41332
42259
|
"typeMessage": "Введите сообщение...",
|
|
41333
42260
|
"sendMessageAria": "Отправить сообщение",
|
|
41334
42261
|
"domainNotValidated": "Домен не проверен",
|
|
41335
|
-
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список."
|
|
42262
|
+
"domainErrorMessage": "Этот домен не в белом списке. Пожалуйста, свяжитесь с администратором, чтобы добавить URL вашего веб-сайта в список.",
|
|
42263
|
+
"aboutTitle": "О приложении",
|
|
42264
|
+
"aboutVersion": "Версия SDK",
|
|
42265
|
+
"aboutConversationId": "ID последнего разговора",
|
|
42266
|
+
"aboutNoConversation": "Разговоров пока нет"
|
|
41336
42267
|
},
|
|
41337
42268
|
"es": {
|
|
41338
42269
|
"landingTitle": "¿Cómo te gustaría comunicarte?",
|
|
@@ -41365,7 +42296,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41365
42296
|
"typeMessage": "Escribe un mensaje...",
|
|
41366
42297
|
"sendMessageAria": "Enviar mensaje",
|
|
41367
42298
|
"domainNotValidated": "Dominio no validado",
|
|
41368
|
-
"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"
|
|
41369
42304
|
},
|
|
41370
42305
|
"fr": {
|
|
41371
42306
|
"landingTitle": "Comment souhaitez-vous communiquer?",
|
|
@@ -41398,7 +42333,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41398
42333
|
"typeMessage": "Tapez votre message...",
|
|
41399
42334
|
"sendMessageAria": "Envoyer un message",
|
|
41400
42335
|
"domainNotValidated": "Domaine non validé",
|
|
41401
|
-
"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"
|
|
41402
42341
|
},
|
|
41403
42342
|
"de": {
|
|
41404
42343
|
"landingTitle": "Wie möchten Sie kommunizieren?",
|
|
@@ -41431,7 +42370,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
41431
42370
|
"typeMessage": "Geben Sie eine Nachricht ein...",
|
|
41432
42371
|
"sendMessageAria": "Nachricht senden",
|
|
41433
42372
|
"domainNotValidated": "Domain nicht validiert",
|
|
41434
|
-
"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"
|
|
41435
42378
|
}
|
|
41436
42379
|
});
|
|
41437
42380
|
|