@xapp/chat-widget 1.91.0 → 1.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ChatTextMessage/ChatTextMessage.d.ts +0 -0
- package/dist/components/Table/Table.d.ts +0 -0
- package/dist/components/Table/index.d.ts +0 -0
- package/dist/index.css +1 -1
- package/dist/index.es.js +180 -56
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +180 -56
- package/dist/index.js.map +1 -1
- package/dist/middlewares/table-middleware.d.ts +0 -0
- package/dist/utils/guards.d.ts +0 -0
- package/dist/xapp/MCPChat.d.ts +0 -0
- package/dist/xapp-chat-widget.css +1 -1
- package/dist/xapp-chat-widget.js +4 -4
- package/dist/xapp-chat-widget.js.map +1 -1
- package/package.json +2 -2
package/dist/index.es.js
CHANGED
|
@@ -3212,9 +3212,11 @@ function getPageContext(override) {
|
|
|
3212
3212
|
}
|
|
3213
3213
|
var MCPChat = /** @class */ (function () {
|
|
3214
3214
|
function MCPChat(config, options) {
|
|
3215
|
+
var _a;
|
|
3215
3216
|
this._userId = "";
|
|
3216
3217
|
this._sessionId = "";
|
|
3217
3218
|
this._accessToken = "";
|
|
3219
|
+
this._debugMode = false;
|
|
3218
3220
|
this._attributes = {};
|
|
3219
3221
|
// Streaming throttle state
|
|
3220
3222
|
this.streamBuffer = "";
|
|
@@ -3237,6 +3239,7 @@ var MCPChat = /** @class */ (function () {
|
|
|
3237
3239
|
this.options = options;
|
|
3238
3240
|
this.configurableMessages = options === null || options === void 0 ? void 0 : options.configurableMessages;
|
|
3239
3241
|
this.isNewSession = false;
|
|
3242
|
+
this._debugMode = (_a = config.debugMode) !== null && _a !== void 0 ? _a : false;
|
|
3240
3243
|
this.hooks = options === null || options === void 0 ? void 0 : options.hooks;
|
|
3241
3244
|
// Validate business_owner mode requires authToken
|
|
3242
3245
|
var mode = config.mode || "homeowner";
|
|
@@ -3280,14 +3283,8 @@ var MCPChat = /** @class */ (function () {
|
|
|
3280
3283
|
// Dispatch bot joined early so it appears before the greeting.
|
|
3281
3284
|
// getBot() is config-derived (uses options.bot), so it's safe to call before setVisitorInfo.
|
|
3282
3285
|
this.userJoined(this.getBot(undefined));
|
|
3283
|
-
//
|
|
3284
|
-
//
|
|
3285
|
-
if (this._sessionId) {
|
|
3286
|
-
this.validateSession();
|
|
3287
|
-
}
|
|
3288
|
-
else {
|
|
3289
|
-
this.initializeNewSession();
|
|
3290
|
-
}
|
|
3286
|
+
// Session initialization is deferred to setVisitorInfo() to avoid
|
|
3287
|
+
// making network requests before the widget is visible.
|
|
3291
3288
|
};
|
|
3292
3289
|
/**
|
|
3293
3290
|
* Validates an existing session with the server ("Silent Handshake").
|
|
@@ -3341,7 +3338,7 @@ var MCPChat = /** @class */ (function () {
|
|
|
3341
3338
|
*/
|
|
3342
3339
|
MCPChat.prototype.buildRequestPayload = function (additionalData) {
|
|
3343
3340
|
if (additionalData === void 0) { additionalData = {}; }
|
|
3344
|
-
return __assign({
|
|
3341
|
+
return __assign(__assign({
|
|
3345
3342
|
// Identity - server generates these, we just send back what we have
|
|
3346
3343
|
userId: this._userId || undefined, sessionId: this._sessionId || undefined,
|
|
3347
3344
|
// Fingerprint for user identification (can be disabled for privacy)
|
|
@@ -3351,7 +3348,7 @@ var MCPChat = /** @class */ (function () {
|
|
|
3351
3348
|
// Client timestamp for latency measurement and clock drift detection
|
|
3352
3349
|
clientTime: new Date().toISOString(),
|
|
3353
3350
|
// Last sequence number for replay on reconnect
|
|
3354
|
-
lastSeq: this.lastSeq }, additionalData);
|
|
3351
|
+
lastSeq: this.lastSeq }, (this._debugMode && { debug: true })), additionalData);
|
|
3355
3352
|
};
|
|
3356
3353
|
/**
|
|
3357
3354
|
* Initializes a new session by calling the endpoint with { newSession: true }.
|
|
@@ -3361,9 +3358,12 @@ var MCPChat = /** @class */ (function () {
|
|
|
3361
3358
|
return __awaiter$1(this, void 0, void 0, function () {
|
|
3362
3359
|
var endpoint, error_2;
|
|
3363
3360
|
var _this = this;
|
|
3364
|
-
|
|
3365
|
-
|
|
3361
|
+
var _a;
|
|
3362
|
+
return __generator$1(this, function (_b) {
|
|
3363
|
+
switch (_b.label) {
|
|
3366
3364
|
case 0:
|
|
3365
|
+
// Reset debug mode on new session (respects config default)
|
|
3366
|
+
this._debugMode = (_a = this.config.debugMode) !== null && _a !== void 0 ? _a : false;
|
|
3367
3367
|
// Prevent multiple concurrent initialization requests
|
|
3368
3368
|
if (this.isInitializingSession) {
|
|
3369
3369
|
log("New session initialization already in progress, skipping");
|
|
@@ -3377,15 +3377,15 @@ var MCPChat = /** @class */ (function () {
|
|
|
3377
3377
|
_this.resolveSessionInit = resolve;
|
|
3378
3378
|
});
|
|
3379
3379
|
this.typing();
|
|
3380
|
-
|
|
3380
|
+
_b.label = 1;
|
|
3381
3381
|
case 1:
|
|
3382
|
-
|
|
3382
|
+
_b.trys.push([1, 3, 4, 5]);
|
|
3383
3383
|
return [4 /*yield*/, this.performSSERequest(this.buildRequestPayload({ newSession: true, generateGreeting: true }))];
|
|
3384
3384
|
case 2:
|
|
3385
|
-
|
|
3385
|
+
_b.sent();
|
|
3386
3386
|
return [3 /*break*/, 5];
|
|
3387
3387
|
case 3:
|
|
3388
|
-
error_2 =
|
|
3388
|
+
error_2 = _b.sent();
|
|
3389
3389
|
err("Failed to initialize new session: ".concat(error_2));
|
|
3390
3390
|
this.stopTyping();
|
|
3391
3391
|
this.setConnectionStatus("offline");
|
|
@@ -3935,10 +3935,28 @@ var MCPChat = /** @class */ (function () {
|
|
|
3935
3935
|
*/
|
|
3936
3936
|
MCPChat.prototype.attemptSSERequest = function (message) {
|
|
3937
3937
|
return __awaiter$1(this, void 0, void 0, function () {
|
|
3938
|
-
var messageText;
|
|
3938
|
+
var messageText, statusMsg, msgId;
|
|
3939
3939
|
var _a;
|
|
3940
3940
|
return __generator$1(this, function (_b) {
|
|
3941
3941
|
messageText = ((_a = message.msg) === null || _a === void 0 ? void 0 : _a.text) || "";
|
|
3942
|
+
// Intercept /debug command — toggle debug mode client-side without sending to LLM
|
|
3943
|
+
if (messageText.trim().toLowerCase() === '/debug') {
|
|
3944
|
+
this._debugMode = !this._debugMode;
|
|
3945
|
+
statusMsg = this._debugMode ? 'Debug mode enabled' : 'Debug mode disabled';
|
|
3946
|
+
log("[attemptSSERequest] ".concat(statusMsg));
|
|
3947
|
+
msgId = "debug-".concat(Date.now());
|
|
3948
|
+
this.dispatch({
|
|
3949
|
+
type: "chat",
|
|
3950
|
+
detail: {
|
|
3951
|
+
type: "chat.stream.end",
|
|
3952
|
+
user: this.getBot(undefined),
|
|
3953
|
+
messageId: msgId,
|
|
3954
|
+
msg: { text: statusMsg },
|
|
3955
|
+
timestamp: +new Date(),
|
|
3956
|
+
},
|
|
3957
|
+
});
|
|
3958
|
+
return [2 /*return*/];
|
|
3959
|
+
}
|
|
3942
3960
|
log("[attemptSSERequest] Sending message: \"".concat(messageText, "\", userId: ").concat(this._userId, ", sessionId: ").concat(this._sessionId));
|
|
3943
3961
|
return [2 /*return*/, this.performSSERequest(this.buildRequestPayload({ message: messageText }))];
|
|
3944
3962
|
});
|
|
@@ -4123,8 +4141,19 @@ var MCPChat = /** @class */ (function () {
|
|
|
4123
4141
|
toolCall.error = data.toolError;
|
|
4124
4142
|
toolCall.label = data.label; // Update with completion label
|
|
4125
4143
|
toolCall.hidden = data.hidden; // Update hidden status
|
|
4126
|
-
|
|
4144
|
+
// Use server-side batch duration if available (debug mode), otherwise client-side
|
|
4145
|
+
toolCall.endTime = (data.toolBatchDurationMs && toolCall.startTime != null)
|
|
4146
|
+
? toolCall.startTime + data.toolBatchDurationMs
|
|
4147
|
+
: Date.now();
|
|
4127
4148
|
toolCall.isExecuting = false;
|
|
4149
|
+
// Capture tool input from debug-enriched events
|
|
4150
|
+
if (data.toolInput) {
|
|
4151
|
+
toolCall.input = data.toolInput;
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
// Toggle debug mode when toggle_debug tool is called by the LLM
|
|
4155
|
+
if (data.toolName === 'toggle_debug') {
|
|
4156
|
+
_this._debugMode = !_this._debugMode;
|
|
4128
4157
|
}
|
|
4129
4158
|
// Always dispatch tool end for user-friendly progress display
|
|
4130
4159
|
_this.dispatchToolEnd({
|
|
@@ -4172,8 +4201,8 @@ var MCPChat = /** @class */ (function () {
|
|
|
4172
4201
|
sources: sources,
|
|
4173
4202
|
displays: data.response.displays,
|
|
4174
4203
|
};
|
|
4175
|
-
// Capture tool calls before flushing (debug mode)
|
|
4176
|
-
var toolCalls_1 = _this.config.debugMode ? __spreadArray$1([], _this.currentToolCalls, true) : undefined;
|
|
4204
|
+
// Capture tool calls before flushing (debug mode — config or runtime toggle)
|
|
4205
|
+
var toolCalls_1 = (_this.config.debugMode || _this._debugMode) ? __spreadArray$1([], _this.currentToolCalls, true) : undefined;
|
|
4177
4206
|
_this.flushStreamBuffer().then(function () {
|
|
4178
4207
|
_this.dispatchStreamEnd(messageId, finalMessage_1, toolCalls_1);
|
|
4179
4208
|
_this.currentToolCalls = []; // Clear after dispatch
|
|
@@ -4268,12 +4297,20 @@ var MCPChat = /** @class */ (function () {
|
|
|
4268
4297
|
this._attributes.currentUrl = window.location.href;
|
|
4269
4298
|
}
|
|
4270
4299
|
this._accessToken = this.visitorInfo.accessToken;
|
|
4271
|
-
|
|
4272
|
-
//
|
|
4300
|
+
this.startSession(sessionId);
|
|
4301
|
+
// Initialize session now that the widget is visible and visitor info is set.
|
|
4302
|
+
// Returning user with existing session - validate session silently
|
|
4303
|
+
// New user without session - initialize new session to get greeting
|
|
4304
|
+
if (this._sessionId) {
|
|
4305
|
+
this.validateSession();
|
|
4306
|
+
}
|
|
4307
|
+
else {
|
|
4308
|
+
this.initializeNewSession();
|
|
4309
|
+
}
|
|
4310
|
+
// Show typing indicator while waiting for session init response
|
|
4273
4311
|
if (this.isInitializingSession) {
|
|
4274
4312
|
this.typing();
|
|
4275
4313
|
}
|
|
4276
|
-
this.startSession(sessionId);
|
|
4277
4314
|
cb();
|
|
4278
4315
|
};
|
|
4279
4316
|
MCPChat.prototype.sendChatRating = function () { };
|
|
@@ -10996,6 +11033,14 @@ function isCard(display) {
|
|
|
10996
11033
|
function isList(display) {
|
|
10997
11034
|
return !!display && (display.type === "LIST" || display.type === "CAROUSEL");
|
|
10998
11035
|
}
|
|
11036
|
+
/**
|
|
11037
|
+
* Is the Display a Table
|
|
11038
|
+
*/
|
|
11039
|
+
function isTable(display) {
|
|
11040
|
+
return !!display && display.type === "TABLE"
|
|
11041
|
+
&& Array.isArray(display.headers)
|
|
11042
|
+
&& Array.isArray(display.rows);
|
|
11043
|
+
}
|
|
10999
11044
|
|
|
11000
11045
|
var CardMiddlewareWidget = function (props) {
|
|
11001
11046
|
var msg = props.msg, ctx = props.ctx;
|
|
@@ -11296,10 +11341,31 @@ var MultiSelectMiddleware = function (next) { return function (props) {
|
|
|
11296
11341
|
return next(props);
|
|
11297
11342
|
}; };
|
|
11298
11343
|
|
|
11344
|
+
var Table = function (_a) {
|
|
11345
|
+
var table = _a.table;
|
|
11346
|
+
return (jsxs("div", { className: "xappw-table", children: [table.title && jsx("div", { className: "xappw-table__header", children: table.title }), jsx("div", { className: "xappw-table__container", children: jsxs("table", { children: [jsx("thead", { children: jsx("tr", { children: table.headers.map(function (header, i) { return (jsx("th", { scope: "col", children: header }, "".concat(header, "-").concat(i))); }) }) }), jsx("tbody", { children: table.rows.map(function (row, rowIndex) { return (jsx("tr", { children: row.map(function (cell, cellIndex) { return (jsx("td", { children: cell }, cellIndex)); }) }, rowIndex)); }) })] }) })] }));
|
|
11347
|
+
};
|
|
11348
|
+
|
|
11349
|
+
var TableMiddlewareWidget = function (props) {
|
|
11350
|
+
var msg = props.msg, ctx = props.ctx;
|
|
11351
|
+
if (!ctx) {
|
|
11352
|
+
throw new TypeError("ctx not provided to ".concat(TableMiddlewareWidget.name));
|
|
11353
|
+
}
|
|
11354
|
+
return (jsx(ChatMessagePart, { showAvatar: false, user: ctx.user, fullWidth: true, children: jsx("div", { className: "chat-msg chat-msg--expand", children: jsx(Table, { table: msg }) }) }));
|
|
11355
|
+
};
|
|
11356
|
+
var TableMiddleware = function (next) { return function (props) {
|
|
11357
|
+
var msg = props.msg, ctx = props.ctx;
|
|
11358
|
+
if (isTable(msg)) {
|
|
11359
|
+
return jsx(TableMiddlewareWidget, { msg: msg, ctx: ctx });
|
|
11360
|
+
}
|
|
11361
|
+
return next(props);
|
|
11362
|
+
}; };
|
|
11363
|
+
|
|
11299
11364
|
var StandardMiddlewaresBuilder = joinMiddlewares([
|
|
11300
11365
|
ListMiddleware,
|
|
11301
11366
|
CardMiddleware,
|
|
11302
|
-
MultiSelectMiddleware
|
|
11367
|
+
MultiSelectMiddleware,
|
|
11368
|
+
TableMiddleware
|
|
11303
11369
|
]);
|
|
11304
11370
|
function useStandardMiddlewareBuilder() {
|
|
11305
11371
|
var lateMiddleware = useLateMiddleware();
|
|
@@ -11553,14 +11619,58 @@ var ToolCallDisplay = function (_a) {
|
|
|
11553
11619
|
};
|
|
11554
11620
|
|
|
11555
11621
|
/**
|
|
11556
|
-
*
|
|
11557
|
-
*
|
|
11622
|
+
* Escape &, <, > for safe insertion into HTML text nodes.
|
|
11623
|
+
* Not suitable for attribute values.
|
|
11558
11624
|
*/
|
|
11625
|
+
function escapeHtml(text) {
|
|
11626
|
+
return text
|
|
11627
|
+
.replace(/&/g, "&")
|
|
11628
|
+
.replace(/</g, "<")
|
|
11629
|
+
.replace(/>/g, ">");
|
|
11630
|
+
}
|
|
11631
|
+
function parseInlineMarkdown(text) {
|
|
11632
|
+
return escapeHtml(text)
|
|
11633
|
+
.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
|
|
11634
|
+
.replace(/__(.+?)__/g, "<strong>$1</strong>")
|
|
11635
|
+
.replace(/\*([^*]+?)\*/g, "<em>$1</em>")
|
|
11636
|
+
.replace(/_([^_]+?)_/g, "<em>$1</em>");
|
|
11637
|
+
}
|
|
11638
|
+
function tableToHtml(headerLine, separatorLine, bodyBlock) {
|
|
11639
|
+
var parseRow = function (row) {
|
|
11640
|
+
return row.split("|").slice(1, -1).map(function (cell) { return parseInlineMarkdown(cell.trim()); });
|
|
11641
|
+
};
|
|
11642
|
+
var separators = separatorLine.split("|").slice(1, -1).map(function (s) { return s.trim(); });
|
|
11643
|
+
var alignments = separators.map(function (sep) {
|
|
11644
|
+
if (sep.startsWith(":") && sep.endsWith(":"))
|
|
11645
|
+
return "center";
|
|
11646
|
+
if (sep.endsWith(":"))
|
|
11647
|
+
return "right";
|
|
11648
|
+
return "left";
|
|
11649
|
+
});
|
|
11650
|
+
var headers = parseRow(headerLine);
|
|
11651
|
+
var headerHtml = headers.map(function (h, i) {
|
|
11652
|
+
return "<th scope=\"col\" style=\"text-align:".concat(alignments[i] || "left", "\">").concat(h, "</th>");
|
|
11653
|
+
}).join("");
|
|
11654
|
+
var bodyRows = bodyBlock.trim().split("\n").filter(function (row) { return row.trim() !== ""; });
|
|
11655
|
+
var bodyHtml = bodyRows.map(function (row) {
|
|
11656
|
+
var cells = parseRow(row);
|
|
11657
|
+
return "<tr>" + cells.map(function (c, i) {
|
|
11658
|
+
return "<td style=\"text-align:".concat(alignments[i] || "left", "\">").concat(c, "</td>");
|
|
11659
|
+
}).join("") + "</tr>";
|
|
11660
|
+
}).join("");
|
|
11661
|
+
return "<div style=\"overflow-x:auto\"><table><thead><tr>".concat(headerHtml, "</tr></thead><tbody>").concat(bodyHtml, "</tbody></table></div>");
|
|
11662
|
+
}
|
|
11559
11663
|
function parseMarkdown(text) {
|
|
11560
11664
|
if (!text)
|
|
11561
11665
|
return "";
|
|
11562
|
-
|
|
11563
|
-
|
|
11666
|
+
// Extract tables first, replace with placeholders, then process the rest
|
|
11667
|
+
var tables = [];
|
|
11668
|
+
var processed = text.replace(/(?:^|\n)(\|.+\|)\n(\|[\s:|-]+\|)\n((?:\|.+\|\n?)+)/g, function (_match, headerLine, separatorLine, bodyBlock) {
|
|
11669
|
+
tables.push(tableToHtml(headerLine, separatorLine, bodyBlock));
|
|
11670
|
+
return "\n%%TABLE".concat(tables.length - 1, "%%\n");
|
|
11671
|
+
});
|
|
11672
|
+
// Now safely escape and parse markdown on the non-table text
|
|
11673
|
+
processed = processed
|
|
11564
11674
|
.replace(/&/g, "&")
|
|
11565
11675
|
.replace(/</g, "<")
|
|
11566
11676
|
.replace(/>/g, ">")
|
|
@@ -11581,13 +11691,17 @@ function parseMarkdown(text) {
|
|
|
11581
11691
|
// Line breaks
|
|
11582
11692
|
.replace(/\n/g, "<br>");
|
|
11583
11693
|
// Wrap consecutive <li> elements in <ul>
|
|
11584
|
-
|
|
11585
|
-
|
|
11694
|
+
processed = processed.replace(/(<li>.*?<\/li>)(<br>)?/g, "$1");
|
|
11695
|
+
processed = processed.replace(/(<li>.*?<\/li>)+/g, "<ul>$&</ul>");
|
|
11586
11696
|
// Clean up <br> inside <ul>
|
|
11587
|
-
|
|
11697
|
+
processed = processed.replace(/<ul>(.*?)<\/ul>/g, function (match) {
|
|
11588
11698
|
return match.replace(/<br>/g, "");
|
|
11589
11699
|
});
|
|
11590
|
-
|
|
11700
|
+
// Restore table placeholders (strip adjacent <br> tags)
|
|
11701
|
+
tables.forEach(function (tableHtml, i) {
|
|
11702
|
+
processed = processed.replace(new RegExp("(?:<br>)?%%TABLE".concat(i, "%%(?:<br>)?")), tableHtml);
|
|
11703
|
+
});
|
|
11704
|
+
return processed;
|
|
11591
11705
|
}
|
|
11592
11706
|
var ChatTextMessage = function (props) {
|
|
11593
11707
|
var _a;
|
|
@@ -35655,7 +35769,7 @@ var ChatWidgetConnected = function (props) {
|
|
|
35655
35769
|
* Exported for use by StaticChatWidgetContainer to avoid infinite loops.
|
|
35656
35770
|
*/
|
|
35657
35771
|
var ChatWidgetUI = function (props) {
|
|
35658
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13
|
|
35772
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
|
|
35659
35773
|
var innerDispatch = useChatDispatch();
|
|
35660
35774
|
var dispatch = useChatServerDispatch();
|
|
35661
35775
|
// From Redux
|
|
@@ -35685,24 +35799,30 @@ var ChatWidgetUI = function (props) {
|
|
|
35685
35799
|
chatState.visuals = {};
|
|
35686
35800
|
}
|
|
35687
35801
|
// Our state - pull from storage
|
|
35688
|
-
|
|
35802
|
+
// Parse autoOpenOnWidth once for use in both initial state and useEffect
|
|
35803
|
+
var autoOpenOnWidthValue = ((_m = props.config) === null || _m === void 0 ? void 0 : _m.autoOpenOnWidth)
|
|
35804
|
+
? parseInt(props.config.autoOpenOnWidth, 10)
|
|
35805
|
+
: NaN;
|
|
35806
|
+
var autoOpenOnWidthMatch = !isNaN(autoOpenOnWidthValue) && window.innerWidth >= autoOpenOnWidthValue;
|
|
35807
|
+
// When autoOpenOnWidth is configured, use width check instead of persisted visible state
|
|
35808
|
+
// to prevent greeting requests on viewports below the threshold
|
|
35809
|
+
var _14 = useState((!canMinimize && !canCancel) ||
|
|
35689
35810
|
// !!get("visible") ||
|
|
35690
|
-
chatState.visuals.visible
|
|
35691
|
-
|
|
35692
|
-
window.matchMedia("(min-width: ".concat((_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnWidth, ")")).matches)), visible = _15[0], setVisibleState = _15[1];
|
|
35693
|
-
var _16 = useState(false); _16[0]; var setTypingState = _16[1]; // false initially - state kept for potential external observers
|
|
35811
|
+
(!isNaN(autoOpenOnWidthValue) ? autoOpenOnWidthMatch : chatState.visuals.visible)), visible = _14[0], setVisibleState = _14[1];
|
|
35812
|
+
var _15 = useState(false); _15[0]; var setTypingState = _15[1]; // false initially - state kept for potential external observers
|
|
35694
35813
|
// Ref to track typing state for use in timeout callbacks
|
|
35695
35814
|
var typingRef = useRef(false);
|
|
35696
35815
|
// Timeout ref for debouncing "stop typing" events
|
|
35697
35816
|
var stopTypingTimeoutRef = useRef(null);
|
|
35817
|
+
// Track whether autoOpenOnWidth has already fired so it doesn't re-open after user closes
|
|
35818
|
+
var autoOpenFiredRef = useRef(autoOpenOnWidthMatch);
|
|
35698
35819
|
var chatServer = useContext(ChatServerContext);
|
|
35699
|
-
var patternsConfig = (
|
|
35820
|
+
var patternsConfig = (_p = (_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnPattern) === null || _p === void 0 ? void 0 : _p.patterns;
|
|
35700
35821
|
var currentUrl = window.location.href;
|
|
35701
35822
|
var patternExist = patternsConfig && patternsConfig.length > 0;
|
|
35702
35823
|
var patternMatches = patternsConfig === null || patternsConfig === void 0 ? void 0 : patternsConfig.some(function (pattern) { return currentUrl.includes(pattern); });
|
|
35703
|
-
var configWidth = (
|
|
35704
|
-
|
|
35705
|
-
var currentWidth = screen.width;
|
|
35824
|
+
var configWidth = (_r = (_q = props.config) === null || _q === void 0 ? void 0 : _q.autoOpenOnPattern) === null || _r === void 0 ? void 0 : _r.minimumWidth;
|
|
35825
|
+
var currentWidth = window.innerWidth;
|
|
35706
35826
|
var setVisible = useCallback(function (newVisible) {
|
|
35707
35827
|
if (staticMode || previewMode) {
|
|
35708
35828
|
return;
|
|
@@ -35736,7 +35856,7 @@ var ChatWidgetUI = function (props) {
|
|
|
35736
35856
|
};
|
|
35737
35857
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35738
35858
|
}, []);
|
|
35739
|
-
var
|
|
35859
|
+
var _16 = useState(!document.hidden), isTabVisible = _16[0], setIsTabVisible = _16[1];
|
|
35740
35860
|
useEffect(function () {
|
|
35741
35861
|
var handleVisibilityChange = function () {
|
|
35742
35862
|
setIsTabVisible(!document.hidden);
|
|
@@ -35785,10 +35905,8 @@ var ChatWidgetUI = function (props) {
|
|
|
35785
35905
|
if (chatState.visuals.opened) {
|
|
35786
35906
|
setVisible(true);
|
|
35787
35907
|
}
|
|
35788
|
-
else {
|
|
35789
|
-
|
|
35790
|
-
setVisible(false);
|
|
35791
|
-
}
|
|
35908
|
+
else if (mode === "normal" && !autoOpenOnWidthMatch) {
|
|
35909
|
+
setVisible(false);
|
|
35792
35910
|
}
|
|
35793
35911
|
if (patternExist && patternMatches) {
|
|
35794
35912
|
setVisible(true);
|
|
@@ -35796,6 +35914,10 @@ var ChatWidgetUI = function (props) {
|
|
|
35796
35914
|
if (currentWidth < +configWidth) {
|
|
35797
35915
|
setVisible(false);
|
|
35798
35916
|
}
|
|
35917
|
+
if (autoOpenOnWidthMatch && !autoOpenFiredRef.current) {
|
|
35918
|
+
autoOpenFiredRef.current = true;
|
|
35919
|
+
setVisible(true);
|
|
35920
|
+
}
|
|
35799
35921
|
}, [
|
|
35800
35922
|
currentWidth,
|
|
35801
35923
|
patternExist,
|
|
@@ -35804,6 +35926,7 @@ var ChatWidgetUI = function (props) {
|
|
|
35804
35926
|
setVisible,
|
|
35805
35927
|
chatState.visuals.opened,
|
|
35806
35928
|
mode,
|
|
35929
|
+
autoOpenOnWidthMatch,
|
|
35807
35930
|
]);
|
|
35808
35931
|
var stopTyping = useCallback(function () {
|
|
35809
35932
|
if (!typingRef.current)
|
|
@@ -35951,8 +36074,8 @@ var ChatWidgetUI = function (props) {
|
|
|
35951
36074
|
}));
|
|
35952
36075
|
}
|
|
35953
36076
|
// Action Bar state and handlers
|
|
35954
|
-
var
|
|
35955
|
-
var
|
|
36077
|
+
var _17 = useState(false), formModalOpen = _17[0], setFormModalOpen = _17[1];
|
|
36078
|
+
var _18 = useState(null), activeFormConfig = _18[0], setActiveFormConfig = _18[1];
|
|
35956
36079
|
var handleFormButtonClick = useCallback(function (formButton) {
|
|
35957
36080
|
// If form-widget is configured, use its openForm API
|
|
35958
36081
|
// The form-widget script should already be pre-loaded
|
|
@@ -36019,7 +36142,7 @@ var ChatWidgetUI = function (props) {
|
|
|
36019
36142
|
var messages = chatState && chatState.chats;
|
|
36020
36143
|
log("Rendering - accountStatus: \"".concat(chatState.accountStatus, "\", connectionStatus: \"").concat(chatState.connection.connectionStatus, "\""));
|
|
36021
36144
|
var config = props.config, onConnectionStatusChange = props.onConnectionStatusChange;
|
|
36022
|
-
var actionBarEnabled = ((
|
|
36145
|
+
var actionBarEnabled = ((_s = config === null || config === void 0 ? void 0 : config.actionBar) === null || _s === void 0 ? void 0 : _s.enabled) === true;
|
|
36023
36146
|
// Disable greeting in preview mode
|
|
36024
36147
|
useGreeting(!isOffline && !props.preChatFormEnabled && visible && !previewMode);
|
|
36025
36148
|
var connectionStatus = chatState.connection.connectionStatus;
|
|
@@ -36028,7 +36151,7 @@ var ChatWidgetUI = function (props) {
|
|
|
36028
36151
|
onConnectionStatusChange(connectionStatus);
|
|
36029
36152
|
}
|
|
36030
36153
|
}, [connectionStatus, onConnectionStatusChange]);
|
|
36031
|
-
useExternalScript((
|
|
36154
|
+
useExternalScript((_t = props.config) === null || _t === void 0 ? void 0 : _t.middlewareUrl);
|
|
36032
36155
|
// Pre-load form-widget script if formWidgetKey is provided
|
|
36033
36156
|
useEffect(function () {
|
|
36034
36157
|
if (config === null || config === void 0 ? void 0 : config.formWidgetKey) {
|
|
@@ -36060,15 +36183,15 @@ var ChatWidgetUI = function (props) {
|
|
|
36060
36183
|
};
|
|
36061
36184
|
}, [actionBarEnabled]);
|
|
36062
36185
|
// This is a pseudo agent. It represent's the widget (shown in the header avatar for instance)
|
|
36063
|
-
var widgetAgent = ((
|
|
36186
|
+
var widgetAgent = ((_u = chatState.agents["agent:robot"]) === null || _u === void 0 ? void 0 : _u.user) ||
|
|
36064
36187
|
(config === null || config === void 0 ? void 0 : config.agent) || {
|
|
36065
36188
|
nick: "agent:robot",
|
|
36066
36189
|
avatarPath: config.avatarUrl,
|
|
36067
36190
|
display_name: "Agent",
|
|
36068
36191
|
};
|
|
36069
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()).concat(actionBarEnabled ? " widget-container--with-action-bar" : ""), children: [jsx(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }), jsx(ChatHeader, { accountStatus: chatState.accountStatus, refreshOnClick: handleRestartClick, minimizeOnClick: handleMinimizeClick, cancelOnClick: handleCancelClick, agent: widgetAgent, canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header, menuConfig: config.menu, debugMode: (
|
|
36192
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()).concat(actionBarEnabled ? " widget-container--with-action-bar" : ""), children: [jsx(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }), jsx(ChatHeader, { accountStatus: chatState.accountStatus, refreshOnClick: handleRestartClick, minimizeOnClick: handleMinimizeClick, cancelOnClick: handleCancelClick, agent: widgetAgent, canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header, menuConfig: config.menu, debugMode: (_x = (_w = (_v = props.config) === null || _v === void 0 ? void 0 : _v.connection) === null || _w === void 0 ? void 0 : _w.mcp) === null || _x === void 0 ? void 0 : _x.debugMode, onSubmit: handleOnSubmit }), jsx(MessageList, { visible: visible, queuePosition: chatState.queuePosition, isChatting: chatState.isChatting, isOffline: isOffline, messages: messages, agents: chatState.agents, agent: config === null || config === void 0 ? void 0 : config.agent, lastRatingRequestTimestamp: chatState.lastRatingRequestTimestamp, hasRating: chatState.hasRating, visitorId: chatState.visitorId, hasWsButton: !!chatState.wsButton, messageMiddleware: props.messageMiddleware, textTypingStatusEnabled: (_z = (_y = props.config) === null || _y === void 0 ? void 0 : _y.typingStatus) === null || _z === void 0 ? void 0 : _z.textTypingStatusEnabled, disableAutoScroll: props.disableAutoScroll, onSend: handleSendMessage, onWrite: handleWriteMessage, onOpenUrl: handleOpenUrl, minimizeOnClick: handleMinimizeClick }), jsx("div", { className: "xa-spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : ""), children: jsx("div", { className: "xa-spinner" }) }), connectionStatus === "offline" && jsx(ServerOffline, {}), chatState.wsButton && visible && (jsx(WsButton, { button: chatState.wsButton, onPress: handleWsButtonPress })), jsx(ChatFooter, { isAdmin: config === null || config === void 0 ? void 0 : config.isAdmin, isChatting: chatState.isChatting, placeholder: (_0 = config === null || config === void 0 ? void 0 : config.input) === null || _0 === void 0 ? void 0 : _0.placeholder, sendButtonIcon: (_2 = (_1 = config === null || config === void 0 ? void 0 : config.footer) === null || _1 === void 0 ? void 0 : _1.sendButton) === null || _2 === void 0 ? void 0 : _2.icon, sendButtonIconHover: (_4 = (_3 = config === null || config === void 0 ? void 0 : config.footer) === null || _3 === void 0 ? void 0 : _3.sendButton) === null || _4 === void 0 ? void 0 : _4.iconHover, sendButtonIconDisabled: (_6 = (_5 = config === null || config === void 0 ? void 0 : config.footer) === null || _5 === void 0 ? void 0 : _5.sendButton) === null || _6 === void 0 ? void 0 : _6.iconDisabled, visible: visible, hasWsButton: !!chatState.wsButton, menuConfig: (_7 = props.config) === null || _7 === void 0 ? void 0 : _7.menu, footerConfig: (_8 = props.config) === null || _8 === void 0 ? void 0 : _8.footer, inputConfig: (_9 = props.config) === null || _9 === void 0 ? void 0 : _9.input, disabled: previewMode, onChange: handleOnChange, onSubmit: handleOnSubmit, onFileUpload: handleFileUpload }), jsx("div", { className: "restartModal", ref: modalRef, onClick: handleRestartModalCloseClick, children: jsx(ModalContent, { onClose: handleRestartModalCloseClick, onReset: handleReset }) })] }), actionBarEnabled && config.actionBar ? (jsxs(Fragment, { children: [jsx(ActionBar, { config: __assign(__assign({}, config.actionBar), {
|
|
36070
36193
|
// Use actionBar.cta if set, otherwise fall back to widget-level cta
|
|
36071
|
-
cta: (
|
|
36194
|
+
cta: (_10 = config.actionBar.cta) !== null && _10 !== void 0 ? _10 : config.cta }), visible: visible, chatDisabled: config.disabled, hasUserInteracted: (_11 = chatState.visuals) === null || _11 === void 0 ? void 0 : _11.hasInteracted, onChatClick: chatButtonOnClick, onChatMinimize: handleMinimizeClick, onFormClick: handleFormButtonClick, onCtaDismiss: handleCtaDismiss }), formModalOpen && activeFormConfig && (jsx(FormModal, { config: activeFormConfig, widgetEnv: config, onClose: handleFormModalClose }))] })) : (jsx(ChatButton, { addClass: visible ? "visible" : "", onClick: chatButtonOnClick, config: config === null || config === void 0 ? void 0 : config.cta, imageUrl: (_12 = config === null || config === void 0 ? void 0 : config.chatButton) === null || _12 === void 0 ? void 0 : _12.imageUrl, visible: visible, hasInteracted: (_13 = chatState.visuals) === null || _13 === void 0 ? void 0 : _13.hasInteracted, onCtaDismiss: handleCtaDismiss })), jsx(ErrorOverlay, { enableErrorOverlay: config === null || config === void 0 ? void 0 : config.enableErrorOverlay })] }));
|
|
36072
36195
|
};
|
|
36073
36196
|
/**
|
|
36074
36197
|
* Top-level wrapper that dispatches between preview mode and connected mode.
|
|
@@ -36161,9 +36284,10 @@ var LocalStorage = /** @class */ (function () {
|
|
|
36161
36284
|
function persistStateReducer(storage, initialState, innerReducer) {
|
|
36162
36285
|
var _a;
|
|
36163
36286
|
var obj = (_a = storage.get()) !== null && _a !== void 0 ? _a : initialState;
|
|
36164
|
-
// Clean up
|
|
36287
|
+
// Clean up transient visual state on page load - don't persist across browser refreshes
|
|
36288
|
+
// visible is derived from config (autoOpenOnWidth, autoOpenOnPattern) and visuals.opened
|
|
36165
36289
|
if (obj && obj.visuals) {
|
|
36166
|
-
obj = __assign(__assign({}, obj), { visuals: __assign(__assign({}, obj.visuals), { hasInteracted: undefined }) });
|
|
36290
|
+
obj = __assign(__assign({}, obj), { visuals: __assign(__assign({}, obj.visuals), { hasInteracted: undefined, visible: undefined }) });
|
|
36167
36291
|
}
|
|
36168
36292
|
return function (state, action) {
|
|
36169
36293
|
if (state === void 0) { state = obj; }
|