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