@xinghunm/ai-chat 0.3.0 → 1.0.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/index.d.mts +56 -7
- package/dist/index.d.ts +56 -7
- package/dist/index.js +733 -234
- package/dist/index.mjs +775 -276
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -78,10 +78,18 @@ var DEFAULT_AI_CHAT_LABELS = {
|
|
|
78
78
|
attachmentLimitNotice: "Images exceeded the limit. Only the first 10 images were kept.",
|
|
79
79
|
userRoleLabel: "User",
|
|
80
80
|
assistantRoleLabel: "Assistant",
|
|
81
|
+
expandMessageAriaLabel: "Expand message",
|
|
82
|
+
collapseMessageAriaLabel: "Collapse message",
|
|
83
|
+
expandComposerAriaLabel: "Expand composer",
|
|
84
|
+
collapseComposerAriaLabel: "Collapse composer",
|
|
81
85
|
stoppedResponse: "Response stopped",
|
|
82
86
|
assistantStreamingAriaLabel: "assistant streaming",
|
|
83
87
|
networkError: "Network request failed. Please try again.",
|
|
84
|
-
genericError: "Something went wrong. Please try again."
|
|
88
|
+
genericError: "Something went wrong. Please try again.",
|
|
89
|
+
questionnaireSubmitting: "Submitting...",
|
|
90
|
+
questionnaireSubmitted: "Selection submitted. Waiting for the plan to continue...",
|
|
91
|
+
questionnaireValidationPrefix: "Please complete:",
|
|
92
|
+
questionnaireSubmitFailed: "Failed to submit. Please try again."
|
|
85
93
|
};
|
|
86
94
|
|
|
87
95
|
// src/store/chat-store.ts
|
|
@@ -97,6 +105,24 @@ var resolveSessionTitleFromMessage = (message) => {
|
|
|
97
105
|
}
|
|
98
106
|
return DEFAULT_CHAT_SESSION_TITLE;
|
|
99
107
|
};
|
|
108
|
+
var mergeStreamingBlocks = (existingBlocks, incomingBlocks) => {
|
|
109
|
+
const nextBlocks = [...existingBlocks ?? []];
|
|
110
|
+
incomingBlocks.forEach((incomingBlock) => {
|
|
111
|
+
if (incomingBlock.type !== "questionnaire") {
|
|
112
|
+
nextBlocks.push(incomingBlock);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const existingIndex = nextBlocks.findIndex(
|
|
116
|
+
(block) => block.type === "questionnaire" && block.questionnaire.questionnaireId === incomingBlock.questionnaire.questionnaireId
|
|
117
|
+
);
|
|
118
|
+
if (existingIndex === -1) {
|
|
119
|
+
nextBlocks.push(incomingBlock);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
nextBlocks[existingIndex] = incomingBlock;
|
|
123
|
+
});
|
|
124
|
+
return nextBlocks;
|
|
125
|
+
};
|
|
100
126
|
var finalizeStreamingMessage = (state, sessionId, status, clearError = false) => {
|
|
101
127
|
const message = state.streamingMessageBySession[sessionId];
|
|
102
128
|
const hasRenderableMessagePayload = Boolean(
|
|
@@ -286,10 +312,15 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
286
312
|
const target = state.streamingMessageBySession[sessionId];
|
|
287
313
|
if (!target)
|
|
288
314
|
return;
|
|
315
|
+
const nextBlocks = patch.blocks !== void 0 ? mergeStreamingBlocks(target.blocks, patch.blocks) : target.blocks;
|
|
289
316
|
set({
|
|
290
317
|
streamingMessageBySession: {
|
|
291
318
|
...state.streamingMessageBySession,
|
|
292
|
-
[sessionId]: {
|
|
319
|
+
[sessionId]: {
|
|
320
|
+
...target,
|
|
321
|
+
...patch,
|
|
322
|
+
...patch.blocks !== void 0 ? { blocks: nextBlocks } : {}
|
|
323
|
+
}
|
|
293
324
|
}
|
|
294
325
|
});
|
|
295
326
|
},
|
|
@@ -509,9 +540,27 @@ var DEFAULT_CHAT_TRANSPORT_ENDPOINTS = {
|
|
|
509
540
|
completions: "/chat/completions",
|
|
510
541
|
terminate: "/chat/terminate"
|
|
511
542
|
};
|
|
543
|
+
var createToolExecutionHeaders = (policy) => {
|
|
544
|
+
if (!policy?.enabled) {
|
|
545
|
+
return {};
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
"X-Tool-Approval-Required": String(Boolean(policy.approvalRequired)),
|
|
549
|
+
...typeof policy.approvalTimeoutSec === "number" ? { "X-Tool-Approval-Timeout": String(policy.approvalTimeoutSec) } : {}
|
|
550
|
+
};
|
|
551
|
+
};
|
|
552
|
+
var createModeDefaultHeaders = (mode) => {
|
|
553
|
+
if (mode === "ask" || mode === "plan") {
|
|
554
|
+
return {
|
|
555
|
+
"X-Tool-Approval-Required": "false"
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
return {};
|
|
559
|
+
};
|
|
512
560
|
var createDefaultChatTransport = ({
|
|
513
561
|
apiBaseUrl,
|
|
514
562
|
authToken,
|
|
563
|
+
toolExecutionPolicy,
|
|
515
564
|
streamHeaders,
|
|
516
565
|
transformStreamPacket,
|
|
517
566
|
endpoints,
|
|
@@ -522,6 +571,10 @@ var createDefaultChatTransport = ({
|
|
|
522
571
|
...DEFAULT_CHAT_TRANSPORT_ENDPOINTS,
|
|
523
572
|
...endpoints
|
|
524
573
|
};
|
|
574
|
+
const resolvedStreamHeaders = {
|
|
575
|
+
...createToolExecutionHeaders(toolExecutionPolicy),
|
|
576
|
+
...streamHeaders
|
|
577
|
+
};
|
|
525
578
|
return {
|
|
526
579
|
getModels: () => getChatModels(client, resolvedEndpoints.models),
|
|
527
580
|
startStream: async ({
|
|
@@ -535,12 +588,16 @@ var createDefaultChatTransport = ({
|
|
|
535
588
|
onDone,
|
|
536
589
|
onError
|
|
537
590
|
}) => {
|
|
591
|
+
const requestHeaders = {
|
|
592
|
+
...createModeDefaultHeaders(mode),
|
|
593
|
+
...resolvedStreamHeaders
|
|
594
|
+
};
|
|
538
595
|
await startChatStream({
|
|
539
596
|
apiBaseUrl,
|
|
540
597
|
endpointPath: resolvedEndpoints.completions,
|
|
541
598
|
sessionId,
|
|
542
599
|
authToken,
|
|
543
|
-
requestHeaders
|
|
600
|
+
requestHeaders,
|
|
544
601
|
model,
|
|
545
602
|
mode,
|
|
546
603
|
content,
|
|
@@ -569,6 +626,8 @@ var AiChatProvider = (props) => {
|
|
|
569
626
|
defaultMode,
|
|
570
627
|
labels,
|
|
571
628
|
renderMessageBlock,
|
|
629
|
+
handleQuestionnaireSubmit,
|
|
630
|
+
handleConfirmationSubmit,
|
|
572
631
|
messageRenderOrder,
|
|
573
632
|
enableImageAttachments = true,
|
|
574
633
|
children
|
|
@@ -624,6 +683,8 @@ var AiChatProvider = (props) => {
|
|
|
624
683
|
sendRef,
|
|
625
684
|
retryRef,
|
|
626
685
|
renderMessageBlock,
|
|
686
|
+
handleQuestionnaireSubmit,
|
|
687
|
+
handleConfirmationSubmit,
|
|
627
688
|
messageRenderOrder,
|
|
628
689
|
transformStreamPacket: defaultTransformStreamPacket,
|
|
629
690
|
enableImageAttachments
|
|
@@ -634,6 +695,8 @@ var AiChatProvider = (props) => {
|
|
|
634
695
|
defaultAuthToken,
|
|
635
696
|
defaultTransformStreamPacket,
|
|
636
697
|
enableImageAttachments,
|
|
698
|
+
handleConfirmationSubmit,
|
|
699
|
+
handleQuestionnaireSubmit,
|
|
637
700
|
labels,
|
|
638
701
|
messageRenderOrder,
|
|
639
702
|
renderMessageBlock,
|
|
@@ -943,7 +1006,7 @@ var getTimelineBlockKey = (block, index) => {
|
|
|
943
1006
|
case "confirmation_card":
|
|
944
1007
|
return `${index}:confirmation_card:${block.proposal.proposalId}`;
|
|
945
1008
|
case "result_summary":
|
|
946
|
-
return `${index}:result_summary:${block.summary.
|
|
1009
|
+
return `${index}:result_summary:${block.summary.summaryId}:${block.summary.status}`;
|
|
947
1010
|
case "questionnaire":
|
|
948
1011
|
return `${index}:questionnaire:${block.questionnaire.questionnaireId}`;
|
|
949
1012
|
case "custom":
|
|
@@ -1069,6 +1132,83 @@ var buildAnchoredTimelineSegments = ({
|
|
|
1069
1132
|
};
|
|
1070
1133
|
|
|
1071
1134
|
// src/components/chat-thread/hooks/use-timeline-block-anchors.ts
|
|
1135
|
+
var createTimelineAnchorState = ({
|
|
1136
|
+
messageId,
|
|
1137
|
+
currentBlockKeys
|
|
1138
|
+
}) => ({
|
|
1139
|
+
messageId,
|
|
1140
|
+
previousBlockKeys: currentBlockKeys,
|
|
1141
|
+
timelineBlockAnchors: {},
|
|
1142
|
+
visibleTimelineBlockKeys: {}
|
|
1143
|
+
});
|
|
1144
|
+
var timelineAnchorReducer = (state, action) => {
|
|
1145
|
+
switch (action.type) {
|
|
1146
|
+
case "reset-message":
|
|
1147
|
+
if (state.messageId === action.messageId) {
|
|
1148
|
+
return state;
|
|
1149
|
+
}
|
|
1150
|
+
return createTimelineAnchorState(action);
|
|
1151
|
+
case "sync-anchors": {
|
|
1152
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1153
|
+
const nextAnchors = action.currentBlockKeys.reduce(
|
|
1154
|
+
(acc, blockKey) => {
|
|
1155
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1156
|
+
if (existingAnchor !== void 0) {
|
|
1157
|
+
acc[blockKey] = existingAnchor;
|
|
1158
|
+
return acc;
|
|
1159
|
+
}
|
|
1160
|
+
if (!previousBlockKeys.has(blockKey)) {
|
|
1161
|
+
acc[blockKey] = action.timelineTextStreamLength;
|
|
1162
|
+
}
|
|
1163
|
+
return acc;
|
|
1164
|
+
},
|
|
1165
|
+
{}
|
|
1166
|
+
);
|
|
1167
|
+
const hasAnchorChanged = Object.keys(nextAnchors).length !== Object.keys(state.timelineBlockAnchors).length || Object.entries(nextAnchors).some(
|
|
1168
|
+
([blockKey, anchor]) => state.timelineBlockAnchors[blockKey] !== anchor
|
|
1169
|
+
);
|
|
1170
|
+
const hasPreviousKeysChanged = action.currentBlockKeys.length !== state.previousBlockKeys.length || action.currentBlockKeys.some(
|
|
1171
|
+
(blockKey, index) => state.previousBlockKeys[index] !== blockKey
|
|
1172
|
+
);
|
|
1173
|
+
if (!hasAnchorChanged && !hasPreviousKeysChanged) {
|
|
1174
|
+
return state;
|
|
1175
|
+
}
|
|
1176
|
+
return {
|
|
1177
|
+
...state,
|
|
1178
|
+
previousBlockKeys: action.currentBlockKeys,
|
|
1179
|
+
timelineBlockAnchors: hasAnchorChanged ? nextAnchors : state.timelineBlockAnchors
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
case "sync-visible": {
|
|
1183
|
+
const nextVisibleBlockKeys = action.currentBlockKeys.reduce(
|
|
1184
|
+
(acc, blockKey) => {
|
|
1185
|
+
if (state.visibleTimelineBlockKeys[blockKey]) {
|
|
1186
|
+
acc[blockKey] = true;
|
|
1187
|
+
return acc;
|
|
1188
|
+
}
|
|
1189
|
+
const anchor = action.effectiveTimelineBlockAnchors[blockKey];
|
|
1190
|
+
if (anchor !== void 0 && anchor <= action.displayedTimelineTextLength) {
|
|
1191
|
+
acc[blockKey] = true;
|
|
1192
|
+
}
|
|
1193
|
+
return acc;
|
|
1194
|
+
},
|
|
1195
|
+
{}
|
|
1196
|
+
);
|
|
1197
|
+
const hasVisibleBlockChanged = Object.keys(nextVisibleBlockKeys).length !== Object.keys(state.visibleTimelineBlockKeys).length || Object.keys(nextVisibleBlockKeys).some(
|
|
1198
|
+
(blockKey) => !state.visibleTimelineBlockKeys[blockKey]
|
|
1199
|
+
);
|
|
1200
|
+
if (!hasVisibleBlockChanged) {
|
|
1201
|
+
return state;
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
...state,
|
|
1205
|
+
visibleTimelineBlockKeys: nextVisibleBlockKeys
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
default:
|
|
1209
|
+
return state;
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1072
1212
|
var useTimelineBlockAnchors = ({
|
|
1073
1213
|
blocks,
|
|
1074
1214
|
displayedTimelineTextLength,
|
|
@@ -1076,8 +1216,6 @@ var useTimelineBlockAnchors = ({
|
|
|
1076
1216
|
message,
|
|
1077
1217
|
messageRenderOrder
|
|
1078
1218
|
}) => {
|
|
1079
|
-
const [timelineBlockAnchors, setTimelineBlockAnchors] = (0, import_react6.useState)({});
|
|
1080
|
-
const [visibleTimelineBlockKeys, setVisibleTimelineBlockKeys] = (0, import_react6.useState)({});
|
|
1081
1219
|
const currentTimelineBlockKeys = (0, import_react6.useMemo)(
|
|
1082
1220
|
() => blocks.map((block, index) => getTimelineBlockKey(block, index)).filter((blockKey) => Boolean(blockKey)),
|
|
1083
1221
|
[blocks]
|
|
@@ -1086,20 +1224,22 @@ var useTimelineBlockAnchors = ({
|
|
|
1086
1224
|
() => getTimelineDisplayUnitCount(getTimelineTextStream(message.content, blocks)),
|
|
1087
1225
|
[blocks, message.content]
|
|
1088
1226
|
);
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1227
|
+
const [state, dispatch] = (0, import_react6.useReducer)(
|
|
1228
|
+
timelineAnchorReducer,
|
|
1229
|
+
{
|
|
1230
|
+
messageId: message.id,
|
|
1231
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1232
|
+
},
|
|
1233
|
+
createTimelineAnchorState
|
|
1234
|
+
);
|
|
1094
1235
|
const effectiveTimelineBlockAnchors = (0, import_react6.useMemo)(() => {
|
|
1095
1236
|
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1096
|
-
return timelineBlockAnchors;
|
|
1237
|
+
return state.timelineBlockAnchors;
|
|
1097
1238
|
}
|
|
1098
|
-
const
|
|
1099
|
-
const previousBlockKeys = new Set(previousTimelineState.blockKeys);
|
|
1239
|
+
const previousBlockKeys = new Set(state.previousBlockKeys);
|
|
1100
1240
|
return currentTimelineBlockKeys.reduce(
|
|
1101
1241
|
(acc, blockKey) => {
|
|
1102
|
-
const existingAnchor = timelineBlockAnchors[blockKey];
|
|
1242
|
+
const existingAnchor = state.timelineBlockAnchors[blockKey];
|
|
1103
1243
|
if (existingAnchor !== void 0) {
|
|
1104
1244
|
acc[blockKey] = existingAnchor;
|
|
1105
1245
|
return acc;
|
|
@@ -1109,125 +1249,70 @@ var useTimelineBlockAnchors = ({
|
|
|
1109
1249
|
}
|
|
1110
1250
|
return acc;
|
|
1111
1251
|
},
|
|
1112
|
-
{ ...timelineBlockAnchors }
|
|
1252
|
+
{ ...state.timelineBlockAnchors }
|
|
1113
1253
|
);
|
|
1114
1254
|
}, [
|
|
1115
1255
|
currentTimelineBlockKeys,
|
|
1116
1256
|
isAssistantStreaming,
|
|
1117
1257
|
messageRenderOrder,
|
|
1118
|
-
|
|
1258
|
+
state.previousBlockKeys,
|
|
1259
|
+
state.timelineBlockAnchors,
|
|
1119
1260
|
timelineTextStreamLength
|
|
1120
1261
|
]);
|
|
1121
1262
|
(0, import_react6.useEffect)(() => {
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
previousTimelineStateRef.current = {
|
|
1131
|
-
messageId: message.id,
|
|
1132
|
-
blockKeys: currentTimelineBlockKeys,
|
|
1133
|
-
textLength: timelineTextStreamLength
|
|
1134
|
-
};
|
|
1263
|
+
dispatch({
|
|
1264
|
+
type: "reset-message",
|
|
1265
|
+
messageId: message.id,
|
|
1266
|
+
currentBlockKeys: currentTimelineBlockKeys
|
|
1267
|
+
});
|
|
1268
|
+
}, [currentTimelineBlockKeys, message.id]);
|
|
1269
|
+
(0, import_react6.useEffect)(() => {
|
|
1270
|
+
if (messageRenderOrder !== "timeline" || !isAssistantStreaming) {
|
|
1135
1271
|
return;
|
|
1136
1272
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
acc[blockKey] = existingAnchor;
|
|
1144
|
-
return acc;
|
|
1145
|
-
}
|
|
1146
|
-
if (!previousBlockKeys.has(blockKey)) {
|
|
1147
|
-
acc[blockKey] = timelineTextStreamLength;
|
|
1148
|
-
}
|
|
1149
|
-
return acc;
|
|
1150
|
-
},
|
|
1151
|
-
{}
|
|
1152
|
-
);
|
|
1153
|
-
const hasAnchorChanged = Object.keys(nextAnchors).length !== Object.keys(timelineBlockAnchors).length || Object.entries(nextAnchors).some(
|
|
1154
|
-
([blockKey, anchor]) => timelineBlockAnchors[blockKey] !== anchor
|
|
1155
|
-
);
|
|
1156
|
-
if (hasAnchorChanged) {
|
|
1157
|
-
setTimelineBlockAnchors(nextAnchors);
|
|
1158
|
-
}
|
|
1159
|
-
} else if (messageRenderOrder !== "timeline" && Object.keys(timelineBlockAnchors).length > 0) {
|
|
1160
|
-
setTimelineBlockAnchors({});
|
|
1161
|
-
}
|
|
1162
|
-
previousTimelineStateRef.current = {
|
|
1163
|
-
messageId: message.id,
|
|
1164
|
-
blockKeys: currentTimelineBlockKeys,
|
|
1165
|
-
textLength: timelineTextStreamLength
|
|
1166
|
-
};
|
|
1167
|
-
}, [
|
|
1168
|
-
currentTimelineBlockKeys,
|
|
1169
|
-
isAssistantStreaming,
|
|
1170
|
-
message.id,
|
|
1171
|
-
message.content,
|
|
1172
|
-
messageRenderOrder,
|
|
1173
|
-
timelineBlockAnchors,
|
|
1174
|
-
timelineTextStreamLength,
|
|
1175
|
-
visibleTimelineBlockKeys
|
|
1176
|
-
]);
|
|
1273
|
+
dispatch({
|
|
1274
|
+
type: "sync-anchors",
|
|
1275
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1276
|
+
timelineTextStreamLength
|
|
1277
|
+
});
|
|
1278
|
+
}, [currentTimelineBlockKeys, isAssistantStreaming, messageRenderOrder, timelineTextStreamLength]);
|
|
1177
1279
|
(0, import_react6.useEffect)(() => {
|
|
1178
1280
|
if (messageRenderOrder !== "timeline") {
|
|
1179
|
-
if (Object.keys(visibleTimelineBlockKeys).length > 0) {
|
|
1180
|
-
setVisibleTimelineBlockKeys({});
|
|
1181
|
-
}
|
|
1182
1281
|
return;
|
|
1183
1282
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
const anchor = effectiveTimelineBlockAnchors[blockKey];
|
|
1191
|
-
if (anchor !== void 0 && anchor <= displayedTimelineTextLength) {
|
|
1192
|
-
acc[blockKey] = true;
|
|
1193
|
-
}
|
|
1194
|
-
return acc;
|
|
1195
|
-
},
|
|
1196
|
-
{}
|
|
1197
|
-
);
|
|
1198
|
-
const hasVisibleBlockChanged = Object.keys(nextVisibleBlockKeys).length !== Object.keys(visibleTimelineBlockKeys).length || Object.keys(nextVisibleBlockKeys).some((blockKey) => !visibleTimelineBlockKeys[blockKey]);
|
|
1199
|
-
if (hasVisibleBlockChanged) {
|
|
1200
|
-
setVisibleTimelineBlockKeys(nextVisibleBlockKeys);
|
|
1201
|
-
}
|
|
1283
|
+
dispatch({
|
|
1284
|
+
type: "sync-visible",
|
|
1285
|
+
currentBlockKeys: currentTimelineBlockKeys,
|
|
1286
|
+
effectiveTimelineBlockAnchors,
|
|
1287
|
+
displayedTimelineTextLength
|
|
1288
|
+
});
|
|
1202
1289
|
}, [
|
|
1203
1290
|
currentTimelineBlockKeys,
|
|
1204
1291
|
displayedTimelineTextLength,
|
|
1205
1292
|
effectiveTimelineBlockAnchors,
|
|
1206
|
-
messageRenderOrder
|
|
1207
|
-
timelineBlockAnchors,
|
|
1208
|
-
visibleTimelineBlockKeys
|
|
1293
|
+
messageRenderOrder
|
|
1209
1294
|
]);
|
|
1210
1295
|
return {
|
|
1211
|
-
timelineBlockAnchors: effectiveTimelineBlockAnchors,
|
|
1212
|
-
visibleTimelineBlockKeys
|
|
1296
|
+
timelineBlockAnchors: messageRenderOrder === "timeline" ? effectiveTimelineBlockAnchors : {},
|
|
1297
|
+
visibleTimelineBlockKeys: messageRenderOrder === "timeline" ? state.visibleTimelineBlockKeys : {}
|
|
1213
1298
|
};
|
|
1214
1299
|
};
|
|
1215
1300
|
|
|
1216
|
-
// src/components/chat-thread/components/
|
|
1301
|
+
// src/components/chat-thread/components/execution-confirmation-card.tsx
|
|
1217
1302
|
var import_styled = __toESM(require("@emotion/styled"));
|
|
1218
1303
|
var import_jsx_runtime2 = require("@emotion/react/jsx-runtime");
|
|
1219
|
-
var
|
|
1304
|
+
var ExecutionConfirmationCard = ({
|
|
1220
1305
|
proposal,
|
|
1221
1306
|
interactive = false,
|
|
1222
1307
|
onApply,
|
|
1223
1308
|
onConfirm,
|
|
1224
1309
|
onRevise
|
|
1225
1310
|
}) => {
|
|
1226
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Card, { "data-testid": "
|
|
1311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Card, { "data-testid": "execution-confirmation-card", children: [
|
|
1227
1312
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Header, { children: [
|
|
1228
1313
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Eyebrow, { children: "Execution Proposal" }),
|
|
1229
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Title, { children: proposal.
|
|
1230
|
-
proposal.
|
|
1314
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Title, { children: proposal.resourceName }),
|
|
1315
|
+
proposal.executorName ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Subtitle, { children: proposal.executorName }) : null
|
|
1231
1316
|
] }),
|
|
1232
1317
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SummaryList, { children: proposal.parameterSummary.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(SummaryItem, { children: [
|
|
1233
1318
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SummaryLabel, { children: item.label }),
|
|
@@ -1235,21 +1320,13 @@ var PDEAIExecutionConfirmationCard = ({
|
|
|
1235
1320
|
] }, `${item.fieldPath ?? item.label}-${item.value}`)) }),
|
|
1236
1321
|
proposal.warnings?.length ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Warnings, { children: proposal.warnings.map((warning) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Warning, { children: warning }, warning)) }) : null,
|
|
1237
1322
|
interactive ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Actions, { children: [
|
|
1238
|
-
onApply && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ActionButton, { type: "button", "data-testid": "
|
|
1239
|
-
onConfirm && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1240
|
-
ActionButton,
|
|
1241
|
-
{
|
|
1242
|
-
type: "button",
|
|
1243
|
-
"data-testid": "pde-ai-confirmation-confirm",
|
|
1244
|
-
onClick: onConfirm,
|
|
1245
|
-
children: "Confirm Execution"
|
|
1246
|
-
}
|
|
1247
|
-
),
|
|
1323
|
+
onApply && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ActionButton, { type: "button", "data-testid": "confirmation-apply", onClick: onApply, children: "Apply to Parameters" }),
|
|
1324
|
+
onConfirm && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ActionButton, { type: "button", "data-testid": "confirmation-confirm", onClick: onConfirm, children: "Confirm Execution" }),
|
|
1248
1325
|
onRevise && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1249
1326
|
SecondaryActionButton,
|
|
1250
1327
|
{
|
|
1251
1328
|
type: "button",
|
|
1252
|
-
"data-testid": "
|
|
1329
|
+
"data-testid": "confirmation-revise",
|
|
1253
1330
|
onClick: onRevise,
|
|
1254
1331
|
children: "Revise Plan"
|
|
1255
1332
|
}
|
|
@@ -1346,10 +1423,10 @@ var SecondaryActionButton = (0, import_styled.default)(ActionButton)`
|
|
|
1346
1423
|
border: 1px solid rgba(255, 255, 255, 0.14);
|
|
1347
1424
|
`;
|
|
1348
1425
|
|
|
1349
|
-
// src/components/chat-thread/components/
|
|
1426
|
+
// src/components/chat-thread/components/notice-card.tsx
|
|
1350
1427
|
var import_styled2 = __toESM(require("@emotion/styled"));
|
|
1351
1428
|
var import_jsx_runtime3 = require("@emotion/react/jsx-runtime");
|
|
1352
|
-
var
|
|
1429
|
+
var NoticeCard = ({ text, tone }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Card2, { "data-testid": "notice-card", "data-tone": tone, children: text });
|
|
1353
1430
|
var Card2 = import_styled2.default.div`
|
|
1354
1431
|
padding: 12px 14px;
|
|
1355
1432
|
border-radius: 16px;
|
|
@@ -1375,10 +1452,10 @@ var Card2 = import_styled2.default.div`
|
|
|
1375
1452
|
}
|
|
1376
1453
|
`;
|
|
1377
1454
|
|
|
1378
|
-
// src/components/chat-thread/components/
|
|
1455
|
+
// src/components/chat-thread/components/parameter-summary-card.tsx
|
|
1379
1456
|
var import_styled3 = __toESM(require("@emotion/styled"));
|
|
1380
1457
|
var import_jsx_runtime4 = require("@emotion/react/jsx-runtime");
|
|
1381
|
-
var
|
|
1458
|
+
var ParameterSummaryCard = ({ items }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Card3, { "data-testid": "parameter-summary-card", children: [
|
|
1382
1459
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Title2, { children: "Parameter Summary" }),
|
|
1383
1460
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(List, { children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ListItem, { children: [
|
|
1384
1461
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Label, { children: item.label }),
|
|
@@ -1422,11 +1499,17 @@ var Value = import_styled3.default.span`
|
|
|
1422
1499
|
text-align: right;
|
|
1423
1500
|
`;
|
|
1424
1501
|
|
|
1425
|
-
// src/components/chat-thread/components/
|
|
1502
|
+
// src/components/chat-thread/components/questionnaire-card.tsx
|
|
1426
1503
|
var import_react7 = require("react");
|
|
1427
1504
|
var import_styled4 = __toESM(require("@emotion/styled"));
|
|
1428
1505
|
var import_jsx_runtime5 = require("@emotion/react/jsx-runtime");
|
|
1429
1506
|
var OTHER_OPTION_VALUE = "__other__";
|
|
1507
|
+
var DEFAULT_QUESTIONNAIRE_CARD_LABELS = {
|
|
1508
|
+
submitting: "Submitting...",
|
|
1509
|
+
submitted: "Selection submitted. Waiting for the plan to continue...",
|
|
1510
|
+
validationPrefix: "Please complete:",
|
|
1511
|
+
submitFailed: "Failed to submit. Please try again."
|
|
1512
|
+
};
|
|
1430
1513
|
var createInitialAnswers = (questionnaire) => ({
|
|
1431
1514
|
...questionnaire.answers ?? {}
|
|
1432
1515
|
});
|
|
@@ -1520,26 +1603,40 @@ var normalizeQuestionAnswer = (question, answer) => {
|
|
|
1520
1603
|
return answer;
|
|
1521
1604
|
}
|
|
1522
1605
|
};
|
|
1523
|
-
var
|
|
1606
|
+
var QuestionnaireCardInner = ({
|
|
1524
1607
|
questionnaire,
|
|
1525
1608
|
interactive = false,
|
|
1526
|
-
onSubmit
|
|
1609
|
+
onSubmit,
|
|
1610
|
+
labels
|
|
1527
1611
|
}) => {
|
|
1528
1612
|
const [answers, setAnswers] = (0, import_react7.useState)(
|
|
1529
1613
|
() => createInitialAnswers(questionnaire)
|
|
1530
1614
|
);
|
|
1531
1615
|
const [errorMessage, setErrorMessage] = (0, import_react7.useState)(null);
|
|
1532
|
-
const
|
|
1616
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react7.useState)(false);
|
|
1617
|
+
const [isSubmitted, setIsSubmitted] = (0, import_react7.useState)(false);
|
|
1618
|
+
const resolvedLabels = {
|
|
1619
|
+
...DEFAULT_QUESTIONNAIRE_CARD_LABELS,
|
|
1620
|
+
...labels
|
|
1621
|
+
};
|
|
1622
|
+
const hasExternalFailureStatus = questionnaire.status === "expired" || questionnaire.status === "failed";
|
|
1623
|
+
const visibleErrorMessage = questionnaire.statusMessage ?? errorMessage;
|
|
1624
|
+
const isInteractionLocked = !interactive || isSubmitting || isSubmitted || hasExternalFailureStatus;
|
|
1625
|
+
const handleSubmit = async () => {
|
|
1626
|
+
if (isSubmitting || isSubmitted) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1533
1629
|
const missingQuestions = questionnaire.questions.filter(
|
|
1534
1630
|
(question) => question.required && isMissingRequiredAnswer(question, answers)
|
|
1535
1631
|
);
|
|
1536
1632
|
if (missingQuestions.length > 0) {
|
|
1537
1633
|
setErrorMessage(
|
|
1538
|
-
|
|
1634
|
+
`${resolvedLabels.validationPrefix} ${missingQuestions.map((question) => question.label).join(", ")}`
|
|
1539
1635
|
);
|
|
1540
1636
|
return;
|
|
1541
1637
|
}
|
|
1542
1638
|
setErrorMessage(null);
|
|
1639
|
+
setIsSubmitting(true);
|
|
1543
1640
|
const normalizedAnswers = Object.fromEntries(
|
|
1544
1641
|
questionnaire.questions.flatMap((question) => {
|
|
1545
1642
|
const value = normalizeQuestionAnswer(question, answers[question.id]);
|
|
@@ -1556,11 +1653,18 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1556
1653
|
return [`- ${question.label}: ${formatQuestionAnswer(question, value)}`];
|
|
1557
1654
|
})
|
|
1558
1655
|
];
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1656
|
+
try {
|
|
1657
|
+
await onSubmit?.({
|
|
1658
|
+
questionnaireId: questionnaire.questionnaireId,
|
|
1659
|
+
answers: normalizedAnswers,
|
|
1660
|
+
content: contentLines.join("\n")
|
|
1661
|
+
});
|
|
1662
|
+
setIsSubmitted(true);
|
|
1663
|
+
} catch (error) {
|
|
1664
|
+
setErrorMessage(error instanceof Error ? error.message : resolvedLabels.submitFailed);
|
|
1665
|
+
} finally {
|
|
1666
|
+
setIsSubmitting(false);
|
|
1667
|
+
}
|
|
1564
1668
|
};
|
|
1565
1669
|
const renderQuestion = (question) => {
|
|
1566
1670
|
const renderOptionChoice = ({
|
|
@@ -1575,13 +1679,13 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1575
1679
|
OptionChoiceItem,
|
|
1576
1680
|
{
|
|
1577
1681
|
role: "button",
|
|
1578
|
-
tabIndex:
|
|
1682
|
+
tabIndex: isInteractionLocked ? -1 : 0,
|
|
1579
1683
|
"aria-pressed": isSelected,
|
|
1580
1684
|
"data-selected": isSelected,
|
|
1581
1685
|
"data-tone": tone,
|
|
1582
|
-
"data-testid": `
|
|
1686
|
+
"data-testid": `question-option-${questionId}-${index}`,
|
|
1583
1687
|
onClick: (event) => {
|
|
1584
|
-
if (
|
|
1688
|
+
if (isInteractionLocked) {
|
|
1585
1689
|
return;
|
|
1586
1690
|
}
|
|
1587
1691
|
if (event.target instanceof HTMLElement && event.target.closest("input")) {
|
|
@@ -1590,7 +1694,7 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1590
1694
|
onClick();
|
|
1591
1695
|
},
|
|
1592
1696
|
onKeyDown: (event) => {
|
|
1593
|
-
if (
|
|
1697
|
+
if (isInteractionLocked) {
|
|
1594
1698
|
return;
|
|
1595
1699
|
}
|
|
1596
1700
|
if (event.key !== "Enter" && event.key !== " ") {
|
|
@@ -1649,11 +1753,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1649
1753
|
inlineInput: singleSelectDraft.selectedValue === OTHER_OPTION_VALUE ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1650
1754
|
InlineOtherInput,
|
|
1651
1755
|
{
|
|
1652
|
-
"data-testid": `
|
|
1756
|
+
"data-testid": `question-input-${question.id}`,
|
|
1653
1757
|
type: "text",
|
|
1654
1758
|
value: singleSelectDraft.otherValue,
|
|
1655
1759
|
placeholder: "Other",
|
|
1656
|
-
readOnly:
|
|
1760
|
+
readOnly: isInteractionLocked,
|
|
1657
1761
|
onClick: (event) => {
|
|
1658
1762
|
event.stopPropagation();
|
|
1659
1763
|
},
|
|
@@ -1674,11 +1778,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1674
1778
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionBody, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1675
1779
|
TextInput,
|
|
1676
1780
|
{
|
|
1677
|
-
"data-testid": `
|
|
1781
|
+
"data-testid": `question-input-${question.id}`,
|
|
1678
1782
|
type: "text",
|
|
1679
1783
|
value: getTextInputValue(answers[question.id]),
|
|
1680
1784
|
placeholder: question.placeholder,
|
|
1681
|
-
readOnly:
|
|
1785
|
+
readOnly: isInteractionLocked,
|
|
1682
1786
|
onChange: (event) => {
|
|
1683
1787
|
setAnswers((current) => updateAnswerValue(current, question.id, event.target.value));
|
|
1684
1788
|
}
|
|
@@ -1689,11 +1793,11 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1689
1793
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1690
1794
|
TextInput,
|
|
1691
1795
|
{
|
|
1692
|
-
"data-testid": `
|
|
1796
|
+
"data-testid": `question-input-${question.id}`,
|
|
1693
1797
|
type: "number",
|
|
1694
1798
|
value: getNumberInputValue(answers[question.id]),
|
|
1695
1799
|
placeholder: question.placeholder,
|
|
1696
|
-
readOnly:
|
|
1800
|
+
readOnly: isInteractionLocked,
|
|
1697
1801
|
onChange: (event) => {
|
|
1698
1802
|
setAnswers(
|
|
1699
1803
|
(current) => updateAnswerValue(
|
|
@@ -1728,7 +1832,7 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1728
1832
|
return null;
|
|
1729
1833
|
}
|
|
1730
1834
|
};
|
|
1731
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card4, { "data-testid": "
|
|
1835
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Card4, { "data-testid": "questionnaire-card", children: [
|
|
1732
1836
|
questionnaire.title ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Title3, { children: questionnaire.title }) : null,
|
|
1733
1837
|
questionnaire.description ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Description, { children: questionnaire.description }) : null,
|
|
1734
1838
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionList, { children: questionnaire.questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(QuestionCard, { children: [
|
|
@@ -1738,24 +1842,28 @@ var PDEAIQuestionnaireCardInner = ({
|
|
|
1738
1842
|
] }),
|
|
1739
1843
|
renderQuestion(question)
|
|
1740
1844
|
] }, question.id)) }),
|
|
1741
|
-
|
|
1742
|
-
interactive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1845
|
+
visibleErrorMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ErrorMessage, { "data-testid": "questionnaire-error", children: visibleErrorMessage }) : null,
|
|
1846
|
+
isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SuccessMessage, { "data-testid": "questionnaire-success", children: resolvedLabels.submitted }) : interactive && !hasExternalFailureStatus ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1743
1847
|
SubmitButton,
|
|
1744
1848
|
{
|
|
1745
1849
|
type: "button",
|
|
1746
|
-
"data-testid": "
|
|
1747
|
-
|
|
1748
|
-
|
|
1850
|
+
"data-testid": "questionnaire-submit",
|
|
1851
|
+
disabled: isInteractionLocked,
|
|
1852
|
+
onClick: () => {
|
|
1853
|
+
void handleSubmit();
|
|
1854
|
+
},
|
|
1855
|
+
children: isSubmitting ? resolvedLabels.submitting : questionnaire.submitLabel ?? "Submit"
|
|
1749
1856
|
}
|
|
1750
1857
|
) : null
|
|
1751
1858
|
] });
|
|
1752
1859
|
};
|
|
1753
1860
|
var getQuestionnaireStateKey = (questionnaire) => JSON.stringify([
|
|
1754
1861
|
questionnaire.questionnaireId,
|
|
1755
|
-
questionnaire.
|
|
1756
|
-
questionnaire.
|
|
1862
|
+
questionnaire.questions,
|
|
1863
|
+
questionnaire.status,
|
|
1864
|
+
questionnaire.statusMessage
|
|
1757
1865
|
]);
|
|
1758
|
-
var
|
|
1866
|
+
var QuestionnaireCard = (props) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QuestionnaireCardInner, { ...props }, getQuestionnaireStateKey(props.questionnaire));
|
|
1759
1867
|
var Card4 = import_styled4.default.section`
|
|
1760
1868
|
display: grid;
|
|
1761
1869
|
gap: 14px;
|
|
@@ -1903,6 +2011,10 @@ var ErrorMessage = import_styled4.default.div`
|
|
|
1903
2011
|
color: rgba(255, 145, 145, 0.96);
|
|
1904
2012
|
font-size: 12px;
|
|
1905
2013
|
`;
|
|
2014
|
+
var SuccessMessage = import_styled4.default.div`
|
|
2015
|
+
color: rgba(164, 255, 210, 0.96);
|
|
2016
|
+
font-size: 12px;
|
|
2017
|
+
`;
|
|
1906
2018
|
var SubmitButton = import_styled4.default.button`
|
|
1907
2019
|
justify-self: flex-start;
|
|
1908
2020
|
border: none;
|
|
@@ -1913,12 +2025,17 @@ var SubmitButton = import_styled4.default.button`
|
|
|
1913
2025
|
font-weight: 700;
|
|
1914
2026
|
padding: 10px 14px;
|
|
1915
2027
|
cursor: pointer;
|
|
2028
|
+
|
|
2029
|
+
&:disabled {
|
|
2030
|
+
cursor: default;
|
|
2031
|
+
opacity: 0.72;
|
|
2032
|
+
}
|
|
1916
2033
|
`;
|
|
1917
2034
|
|
|
1918
|
-
// src/components/chat-thread/components/
|
|
2035
|
+
// src/components/chat-thread/components/result-summary-card.tsx
|
|
1919
2036
|
var import_styled5 = __toESM(require("@emotion/styled"));
|
|
1920
2037
|
var import_jsx_runtime6 = require("@emotion/react/jsx-runtime");
|
|
1921
|
-
var
|
|
2038
|
+
var ResultSummaryCard = ({ summary }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Card5, { "data-testid": "result-summary-card", "data-status": summary.status, children: [
|
|
1922
2039
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Eyebrow2, { children: summary.status }),
|
|
1923
2040
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Headline, { children: summary.headline }),
|
|
1924
2041
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Details, { children: summary.details.map((detail) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Detail, { children: detail }, detail)) })
|
|
@@ -2014,6 +2131,7 @@ var ImageViewer = ({ src, alt, onClose }) => {
|
|
|
2014
2131
|
var import_jsx_runtime8 = require("@emotion/react/jsx-runtime");
|
|
2015
2132
|
var MARKDOWN_REMARK_PLUGINS = [import_remark_gfm.default, import_remark_math.default];
|
|
2016
2133
|
var MARKDOWN_REHYPE_PLUGINS = [import_rehype_katex.default];
|
|
2134
|
+
var USER_MESSAGE_COLLAPSE_HEIGHT_PX = 120;
|
|
2017
2135
|
var MARKDOWN_COMPONENTS = {
|
|
2018
2136
|
table: ({ node: _node, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TableWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("table", { ...props }) })
|
|
2019
2137
|
};
|
|
@@ -2026,10 +2144,101 @@ var renderMarkdownContent = (content) => /* @__PURE__ */ (0, import_jsx_runtime8
|
|
|
2026
2144
|
children: content
|
|
2027
2145
|
}
|
|
2028
2146
|
);
|
|
2147
|
+
var renderPlainTextContent = (content) => content;
|
|
2148
|
+
var CollapseIcon = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2149
|
+
"svg",
|
|
2150
|
+
{
|
|
2151
|
+
"aria-hidden": "true",
|
|
2152
|
+
width: "16",
|
|
2153
|
+
height: "16",
|
|
2154
|
+
viewBox: "0 0 16 16",
|
|
2155
|
+
fill: "none",
|
|
2156
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2157
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2158
|
+
"path",
|
|
2159
|
+
{
|
|
2160
|
+
d: "M4 6l4 4 4-4",
|
|
2161
|
+
stroke: "currentColor",
|
|
2162
|
+
strokeWidth: "1.6",
|
|
2163
|
+
strokeLinecap: "round",
|
|
2164
|
+
strokeLinejoin: "round",
|
|
2165
|
+
transform: expanded ? "rotate(180 8 8)" : void 0
|
|
2166
|
+
}
|
|
2167
|
+
)
|
|
2168
|
+
}
|
|
2169
|
+
);
|
|
2170
|
+
var useUserMessageCollapse = ({
|
|
2171
|
+
blocks,
|
|
2172
|
+
displayedBlocks,
|
|
2173
|
+
displayedContent,
|
|
2174
|
+
enabled,
|
|
2175
|
+
freshContent,
|
|
2176
|
+
settledContent
|
|
2177
|
+
}) => {
|
|
2178
|
+
const [isCollapsible, setIsCollapsible] = (0, import_react9.useState)(false);
|
|
2179
|
+
const [isExpanded, setIsExpanded] = (0, import_react9.useState)(false);
|
|
2180
|
+
const [bodyStackElement, setBodyStackElement] = (0, import_react9.useState)(null);
|
|
2181
|
+
const syncCollapseState = (0, import_react9.useCallback)(
|
|
2182
|
+
(element) => {
|
|
2183
|
+
const nextCollapsible = enabled && (element?.scrollHeight ?? 0) > USER_MESSAGE_COLLAPSE_HEIGHT_PX;
|
|
2184
|
+
setIsCollapsible(nextCollapsible);
|
|
2185
|
+
if (!nextCollapsible) {
|
|
2186
|
+
setIsExpanded(false);
|
|
2187
|
+
}
|
|
2188
|
+
},
|
|
2189
|
+
[enabled]
|
|
2190
|
+
);
|
|
2191
|
+
const bodyStackRef = (0, import_react9.useCallback)(
|
|
2192
|
+
(node) => {
|
|
2193
|
+
setBodyStackElement(node);
|
|
2194
|
+
syncCollapseState(node);
|
|
2195
|
+
},
|
|
2196
|
+
[syncCollapseState]
|
|
2197
|
+
);
|
|
2198
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
2199
|
+
if (!bodyStackElement) {
|
|
2200
|
+
return;
|
|
2201
|
+
}
|
|
2202
|
+
const frameId = requestAnimationFrame(() => {
|
|
2203
|
+
syncCollapseState(bodyStackElement);
|
|
2204
|
+
});
|
|
2205
|
+
return () => {
|
|
2206
|
+
cancelAnimationFrame(frameId);
|
|
2207
|
+
};
|
|
2208
|
+
}, [
|
|
2209
|
+
blocks,
|
|
2210
|
+
bodyStackElement,
|
|
2211
|
+
displayedBlocks,
|
|
2212
|
+
displayedContent,
|
|
2213
|
+
enabled,
|
|
2214
|
+
freshContent,
|
|
2215
|
+
settledContent,
|
|
2216
|
+
syncCollapseState
|
|
2217
|
+
]);
|
|
2218
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
2219
|
+
if (!bodyStackElement || !enabled || typeof ResizeObserver === "undefined") {
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
const observer = new ResizeObserver(() => {
|
|
2223
|
+
syncCollapseState(bodyStackElement);
|
|
2224
|
+
});
|
|
2225
|
+
observer.observe(bodyStackElement);
|
|
2226
|
+
return () => {
|
|
2227
|
+
observer.disconnect();
|
|
2228
|
+
};
|
|
2229
|
+
}, [bodyStackElement, enabled, syncCollapseState]);
|
|
2230
|
+
return {
|
|
2231
|
+
bodyStackRef,
|
|
2232
|
+
isCollapsed: isCollapsible && !isExpanded,
|
|
2233
|
+
isCollapsible,
|
|
2234
|
+
isExpanded,
|
|
2235
|
+
toggleExpanded: () => setIsExpanded((current) => !current)
|
|
2236
|
+
};
|
|
2237
|
+
};
|
|
2029
2238
|
var createExecutionConfirmationContent = (proposal) => [
|
|
2030
2239
|
"Execution confirmed",
|
|
2031
|
-
`- Equation: ${proposal.
|
|
2032
|
-
...proposal.
|
|
2240
|
+
`- Equation: ${proposal.resourceName}`,
|
|
2241
|
+
...proposal.executorName ? [`- Solver: ${proposal.executorName}`] : [],
|
|
2033
2242
|
`- Proposal ID: ${proposal.proposalId}`
|
|
2034
2243
|
].join("\n");
|
|
2035
2244
|
var areChatAttachmentsEqual = (previousAttachments, nextAttachments) => {
|
|
@@ -2051,10 +2260,10 @@ var areParameterSummaryItemsEqual = (previousItems, nextItems) => previousItems.
|
|
|
2051
2260
|
const nextItem = nextItems[index];
|
|
2052
2261
|
return item.label === nextItem?.label && item.value === nextItem.value && item.fieldPath === nextItem.fieldPath;
|
|
2053
2262
|
});
|
|
2054
|
-
var areExecutionProposalsEqual = (previousProposal, nextProposal) => previousProposal.proposalId === nextProposal.proposalId && previousProposal.
|
|
2263
|
+
var areExecutionProposalsEqual = (previousProposal, nextProposal) => previousProposal.proposalId === nextProposal.proposalId && previousProposal.resourceKey === nextProposal.resourceKey && previousProposal.resourceName === nextProposal.resourceName && previousProposal.executorName === nextProposal.executorName && previousProposal.requiresConfirmation === nextProposal.requiresConfirmation && areParameterSummaryItemsEqual(previousProposal.parameterSummary, nextProposal.parameterSummary) && (previousProposal.warnings ?? []).length === (nextProposal.warnings ?? []).length && (previousProposal.warnings ?? []).every(
|
|
2055
2264
|
(warning, index) => warning === nextProposal.warnings?.[index]
|
|
2056
2265
|
);
|
|
2057
|
-
var areResultSummariesEqual = (previousSummary, nextSummary) => previousSummary.
|
|
2266
|
+
var areResultSummariesEqual = (previousSummary, nextSummary) => previousSummary.summaryId === nextSummary.summaryId && previousSummary.status === nextSummary.status && previousSummary.headline === nextSummary.headline && previousSummary.details.length === nextSummary.details.length && previousSummary.details.every((detail, index) => detail === nextSummary.details[index]);
|
|
2058
2267
|
var areStringArraysEqual = (previousValues, nextValues) => previousValues.length === nextValues.length && previousValues.every((value, index) => value === nextValues[index]);
|
|
2059
2268
|
var areQuestionAnswersEqual = (previousAnswer, nextAnswer) => {
|
|
2060
2269
|
if (Array.isArray(previousAnswer) || Array.isArray(nextAnswer)) {
|
|
@@ -2095,7 +2304,7 @@ var arePlanQuestionsEqual = (previousQuestion, nextQuestion) => {
|
|
|
2095
2304
|
return false;
|
|
2096
2305
|
}
|
|
2097
2306
|
};
|
|
2098
|
-
var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
|
|
2307
|
+
var areQuestionnairesEqual = (previousQuestionnaire, nextQuestionnaire) => previousQuestionnaire.questionnaireId === nextQuestionnaire.questionnaireId && previousQuestionnaire.title === nextQuestionnaire.title && previousQuestionnaire.description === nextQuestionnaire.description && previousQuestionnaire.submitLabel === nextQuestionnaire.submitLabel && previousQuestionnaire.status === nextQuestionnaire.status && previousQuestionnaire.statusMessage === nextQuestionnaire.statusMessage && previousQuestionnaire.questions.length === nextQuestionnaire.questions.length && previousQuestionnaire.questions.every(
|
|
2099
2308
|
(question, index) => arePlanQuestionsEqual(question, nextQuestionnaire.questions[index])
|
|
2100
2309
|
) && areQuestionAnswerMapsEqual(previousQuestionnaire.answers, nextQuestionnaire.answers);
|
|
2101
2310
|
var areMessageBlocksEqual = (previousBlocks, nextBlocks) => {
|
|
@@ -2176,6 +2385,8 @@ var ChatMessageItemView = ({
|
|
|
2176
2385
|
const canSubmitConfirmation = isPlanMode && typeof onConfirmationSubmit === "function";
|
|
2177
2386
|
const canSubmitQuestionnaire = isPlanMode && typeof onQuestionnaireSubmit === "function";
|
|
2178
2387
|
const shouldShowStreamingCaret = isAssistantStreaming && (!shouldRenderStructuredBlocks || hasTextContent);
|
|
2388
|
+
const isUserMessage = message.role === "user";
|
|
2389
|
+
const messageRenderMode = isUserMessage ? "plain-text" : "markdown";
|
|
2179
2390
|
const timelineConsumedText = messageRenderOrder === "timeline" ? getTimelineConsumedText(blocks) : "";
|
|
2180
2391
|
const hasConsumedTimelineText = timelineConsumedText.length > 0 && displayedContent.startsWith(timelineConsumedText);
|
|
2181
2392
|
const timelineDisplayedContent = hasConsumedTimelineText ? displayedContent.slice(timelineConsumedText.length) : displayedContent;
|
|
@@ -2192,6 +2403,21 @@ var ChatMessageItemView = ({
|
|
|
2192
2403
|
message,
|
|
2193
2404
|
messageRenderOrder
|
|
2194
2405
|
});
|
|
2406
|
+
const {
|
|
2407
|
+
bodyStackRef,
|
|
2408
|
+
isCollapsed: isUserMessageCollapsed,
|
|
2409
|
+
isCollapsible: isUserMessageCollapsible,
|
|
2410
|
+
isExpanded: isUserMessageExpanded,
|
|
2411
|
+
toggleExpanded: toggleUserMessageExpanded
|
|
2412
|
+
} = useUserMessageCollapse({
|
|
2413
|
+
blocks,
|
|
2414
|
+
displayedBlocks,
|
|
2415
|
+
displayedContent,
|
|
2416
|
+
enabled: isUserMessage,
|
|
2417
|
+
freshContent,
|
|
2418
|
+
settledContent
|
|
2419
|
+
});
|
|
2420
|
+
const renderMessageContent = (content) => messageRenderMode === "plain-text" ? renderPlainTextContent(content) : renderMarkdownContent(content);
|
|
2195
2421
|
const renderChatMessageBlock = (block, index) => {
|
|
2196
2422
|
switch (block.type) {
|
|
2197
2423
|
case "markdown":
|
|
@@ -2200,17 +2426,18 @@ var ChatMessageItemView = ({
|
|
|
2200
2426
|
{
|
|
2201
2427
|
"data-testid": `chat-message-block-${index}`,
|
|
2202
2428
|
"data-block-tone": "settled",
|
|
2203
|
-
|
|
2429
|
+
"data-render-mode": messageRenderMode,
|
|
2430
|
+
children: renderMessageContent(block.text)
|
|
2204
2431
|
},
|
|
2205
2432
|
`markdown-${index}`
|
|
2206
2433
|
);
|
|
2207
2434
|
case "notice":
|
|
2208
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(NoticeCard, { text: block.text, tone: block.tone }) }, `notice-${index}`);
|
|
2209
2436
|
case "parameter_summary":
|
|
2210
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ParameterSummaryCard, { items: block.items }) }, `parameter-summary-${index}`);
|
|
2211
2438
|
case "confirmation_card":
|
|
2212
2439
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2213
|
-
|
|
2440
|
+
ExecutionConfirmationCard,
|
|
2214
2441
|
{
|
|
2215
2442
|
proposal: block.proposal,
|
|
2216
2443
|
interactive: isPlanMode,
|
|
@@ -2222,13 +2449,19 @@ var ChatMessageItemView = ({
|
|
|
2222
2449
|
}
|
|
2223
2450
|
) }, `confirmation-card-${index}`);
|
|
2224
2451
|
case "result_summary":
|
|
2225
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ResultSummaryCard, { summary: block.summary }) }, `result-summary-${index}`);
|
|
2226
2453
|
case "questionnaire":
|
|
2227
2454
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react9.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2228
|
-
|
|
2455
|
+
QuestionnaireCard,
|
|
2229
2456
|
{
|
|
2230
2457
|
questionnaire: block.questionnaire,
|
|
2231
2458
|
interactive: canSubmitQuestionnaire,
|
|
2459
|
+
labels: {
|
|
2460
|
+
submitting: labels.questionnaireSubmitting,
|
|
2461
|
+
submitted: labels.questionnaireSubmitted,
|
|
2462
|
+
validationPrefix: labels.questionnaireValidationPrefix,
|
|
2463
|
+
submitFailed: labels.questionnaireSubmitFailed
|
|
2464
|
+
},
|
|
2232
2465
|
onSubmit: canSubmitQuestionnaire ? (submission) => onQuestionnaireSubmit({
|
|
2233
2466
|
...submission,
|
|
2234
2467
|
sourceMessageId: message.id
|
|
@@ -2261,14 +2494,31 @@ var ChatMessageItemView = ({
|
|
|
2261
2494
|
"data-testid": block.tone === "fresh" ? "chat-message-fresh-block" : "chat-message-settled-block",
|
|
2262
2495
|
"data-block-tone": block.tone,
|
|
2263
2496
|
"data-block-index": index,
|
|
2264
|
-
|
|
2497
|
+
"data-render-mode": messageRenderMode,
|
|
2498
|
+
children: renderMessageContent(block.content)
|
|
2265
2499
|
},
|
|
2266
2500
|
`${block.tone}-${index}`
|
|
2267
2501
|
)),
|
|
2268
|
-
!textBlocks.some((block) => block.content) && !settledText && !freshText && Boolean(textContent) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2502
|
+
!textBlocks.some((block) => block.content) && !settledText && !freshText && Boolean(textContent) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2503
|
+
ContentBlock,
|
|
2504
|
+
{
|
|
2505
|
+
"data-testid": "chat-message-settled-block",
|
|
2506
|
+
"data-block-tone": "settled",
|
|
2507
|
+
"data-render-mode": messageRenderMode,
|
|
2508
|
+
children: renderMessageContent(textContent)
|
|
2509
|
+
}
|
|
2510
|
+
) : null
|
|
2269
2511
|
] });
|
|
2270
2512
|
};
|
|
2271
|
-
const renderStaticTextSegment = (content) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2513
|
+
const renderStaticTextSegment = (content) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2514
|
+
ContentBlock,
|
|
2515
|
+
{
|
|
2516
|
+
"data-testid": "chat-message-settled-block",
|
|
2517
|
+
"data-block-tone": "settled",
|
|
2518
|
+
"data-render-mode": messageRenderMode,
|
|
2519
|
+
children: renderMessageContent(content)
|
|
2520
|
+
}
|
|
2521
|
+
);
|
|
2272
2522
|
const bodySegments = (() => {
|
|
2273
2523
|
if (!shouldRenderStructuredBlocks && hasTextContent) {
|
|
2274
2524
|
return [{ type: "text" }];
|
|
@@ -2326,21 +2576,40 @@ var ChatMessageItemView = ({
|
|
|
2326
2576
|
}
|
|
2327
2577
|
) : null,
|
|
2328
2578
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Role, { children: message.role === "user" ? labels.userRoleLabel : labels.assistantRoleLabel }),
|
|
2579
|
+
isUserMessageCollapsible ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2580
|
+
CollapseToggle,
|
|
2581
|
+
{
|
|
2582
|
+
type: "button",
|
|
2583
|
+
"data-testid": "chat-message-collapse-toggle",
|
|
2584
|
+
"aria-label": isUserMessageExpanded ? labels.collapseMessageAriaLabel : labels.expandMessageAriaLabel,
|
|
2585
|
+
"aria-expanded": isUserMessageExpanded,
|
|
2586
|
+
onClick: toggleUserMessageExpanded,
|
|
2587
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CollapseIcon, { expanded: isUserMessageExpanded })
|
|
2588
|
+
}
|
|
2589
|
+
) : null,
|
|
2329
2590
|
isStoppedAssistant ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusTag, { "data-testid": "chat-message-stopped-tag", children: labels.stoppedResponse }) : null
|
|
2330
2591
|
] }),
|
|
2331
2592
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Content, { "data-testid": "chat-message-content", children: [
|
|
2332
|
-
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2333
|
-
|
|
2593
|
+
shouldRenderStructuredBlocks || hasTextContent ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2594
|
+
ContentStack,
|
|
2334
2595
|
{
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2596
|
+
ref: bodyStackRef,
|
|
2597
|
+
"data-testid": "chat-message-body-stack",
|
|
2598
|
+
"data-collapsed": isUserMessageCollapsed,
|
|
2599
|
+
children: bodySegments.map((segment, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2600
|
+
ContentSegment,
|
|
2601
|
+
{
|
|
2602
|
+
"data-testid": "chat-message-content-segment",
|
|
2603
|
+
children: segment.type === "block" ? renderChatMessageBlock(segment.block, segment.index) : segment.type === "text" ? segment.content !== void 0 ? segment.useTimelineSegmentation ? renderTextContent({
|
|
2604
|
+
content: segment.content,
|
|
2605
|
+
displayedBlocks: segment.displayedBlocks,
|
|
2606
|
+
useTimelineSegmentation: true
|
|
2607
|
+
}) : renderStaticTextSegment(segment.content) : renderTextContent() : renderStaticTextSegment(segment.content)
|
|
2608
|
+
},
|
|
2609
|
+
segment.type === "text" ? `text-${index}` : segment.type === "markdown" ? `markdown-${index}` : `${segment.block.type}-${segment.index}`
|
|
2610
|
+
))
|
|
2611
|
+
}
|
|
2612
|
+
) : null,
|
|
2344
2613
|
attachments.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AttachmentGrid, { "data-testid": "chat-message-attachment-grid", children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2345
2614
|
AttachmentButton,
|
|
2346
2615
|
{
|
|
@@ -2425,6 +2694,29 @@ var StatusTag = import_styled7.default.span`
|
|
|
2425
2694
|
letter-spacing: 0.02em;
|
|
2426
2695
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
|
2427
2696
|
`;
|
|
2697
|
+
var CollapseToggle = import_styled7.default.button`
|
|
2698
|
+
margin-left: auto;
|
|
2699
|
+
width: 28px;
|
|
2700
|
+
height: 28px;
|
|
2701
|
+
display: inline-flex;
|
|
2702
|
+
align-items: center;
|
|
2703
|
+
justify-content: center;
|
|
2704
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
2705
|
+
border-radius: 999px;
|
|
2706
|
+
background: rgba(255, 255, 255, 0.06);
|
|
2707
|
+
color: rgba(255, 255, 255, 0.72);
|
|
2708
|
+
cursor: pointer;
|
|
2709
|
+
transition:
|
|
2710
|
+
background 160ms ease-out,
|
|
2711
|
+
border-color 160ms ease-out,
|
|
2712
|
+
color 160ms ease-out;
|
|
2713
|
+
|
|
2714
|
+
&:hover {
|
|
2715
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2716
|
+
border-color: rgba(255, 255, 255, 0.18);
|
|
2717
|
+
color: rgba(255, 255, 255, 0.92);
|
|
2718
|
+
}
|
|
2719
|
+
`;
|
|
2428
2720
|
var Content = import_styled7.default.div`
|
|
2429
2721
|
color: rgba(255, 255, 255, 0.92);
|
|
2430
2722
|
line-height: 1.6;
|
|
@@ -2469,6 +2761,11 @@ var ContentStack = import_styled7.default.div`
|
|
|
2469
2761
|
display: flex;
|
|
2470
2762
|
flex-direction: column;
|
|
2471
2763
|
gap: 16px;
|
|
2764
|
+
|
|
2765
|
+
&[data-collapsed='true'] {
|
|
2766
|
+
max-height: ${USER_MESSAGE_COLLAPSE_HEIGHT_PX}px;
|
|
2767
|
+
overflow: hidden;
|
|
2768
|
+
}
|
|
2472
2769
|
`;
|
|
2473
2770
|
var ContentSegment = import_styled7.default.div`
|
|
2474
2771
|
min-width: 0;
|
|
@@ -2482,6 +2779,11 @@ var ContentBlock = import_styled7.default.div`
|
|
|
2482
2779
|
margin-top: 16px;
|
|
2483
2780
|
}
|
|
2484
2781
|
|
|
2782
|
+
&[data-render-mode='plain-text'] {
|
|
2783
|
+
white-space: pre-wrap;
|
|
2784
|
+
overflow-wrap: anywhere;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2485
2787
|
&[data-block-tone='fresh'] {
|
|
2486
2788
|
opacity: 0.85;
|
|
2487
2789
|
filter: brightness(0.82) saturate(0.88);
|
|
@@ -2889,7 +3191,14 @@ var ChatThread = () => {
|
|
|
2889
3191
|
const error = useChatStore((s) => s.errorBySession[s.activeSessionId ?? ""]);
|
|
2890
3192
|
const updateQA = useChatStore((s) => s.updateQuestionnaireAnswers);
|
|
2891
3193
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
2892
|
-
const {
|
|
3194
|
+
const {
|
|
3195
|
+
sendRef,
|
|
3196
|
+
retryRef,
|
|
3197
|
+
renderMessageBlock,
|
|
3198
|
+
handleQuestionnaireSubmit: customQuestionnaireSubmit,
|
|
3199
|
+
handleConfirmationSubmit: customConfirmationSubmit,
|
|
3200
|
+
labels
|
|
3201
|
+
} = useChatContext();
|
|
2893
3202
|
const handleRetry = (0, import_react11.useCallback)(() => {
|
|
2894
3203
|
if (!activeSessionId)
|
|
2895
3204
|
return;
|
|
@@ -2897,7 +3206,25 @@ var ChatThread = () => {
|
|
|
2897
3206
|
void retryRef.current();
|
|
2898
3207
|
}, [activeSessionId, clearSessionError, retryRef]);
|
|
2899
3208
|
const handleQuestionnaireSubmit = (0, import_react11.useCallback)(
|
|
2900
|
-
(submission) => {
|
|
3209
|
+
async (submission) => {
|
|
3210
|
+
if (customQuestionnaireSubmit) {
|
|
3211
|
+
const handled = await customQuestionnaireSubmit(submission, {
|
|
3212
|
+
sessionId: activeSessionId ?? void 0,
|
|
3213
|
+
mode: activeSessionMode
|
|
3214
|
+
});
|
|
3215
|
+
if (handled !== false) {
|
|
3216
|
+
if (activeSessionId && submission.sourceMessageId) {
|
|
3217
|
+
updateQA(
|
|
3218
|
+
activeSessionId,
|
|
3219
|
+
submission.sourceMessageId,
|
|
3220
|
+
submission.questionnaireId,
|
|
3221
|
+
submission.answers
|
|
3222
|
+
);
|
|
3223
|
+
}
|
|
3224
|
+
return;
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
await sendRef.current(submission.content);
|
|
2901
3228
|
if (activeSessionId && submission.sourceMessageId) {
|
|
2902
3229
|
updateQA(
|
|
2903
3230
|
activeSessionId,
|
|
@@ -2906,15 +3233,23 @@ var ChatThread = () => {
|
|
|
2906
3233
|
submission.answers
|
|
2907
3234
|
);
|
|
2908
3235
|
}
|
|
2909
|
-
void sendRef.current(submission.content);
|
|
2910
3236
|
},
|
|
2911
|
-
[activeSessionId, updateQA, sendRef]
|
|
3237
|
+
[activeSessionId, activeSessionMode, updateQA, sendRef, customQuestionnaireSubmit]
|
|
2912
3238
|
);
|
|
2913
|
-
const
|
|
2914
|
-
(submission) => {
|
|
2915
|
-
|
|
3239
|
+
const handleConfirmation = (0, import_react11.useCallback)(
|
|
3240
|
+
async (submission) => {
|
|
3241
|
+
if (customConfirmationSubmit) {
|
|
3242
|
+
const handled = await customConfirmationSubmit(submission, {
|
|
3243
|
+
sessionId: activeSessionId ?? void 0,
|
|
3244
|
+
mode: activeSessionMode
|
|
3245
|
+
});
|
|
3246
|
+
if (handled !== false) {
|
|
3247
|
+
return;
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
await sendRef.current(submission.content);
|
|
2916
3251
|
},
|
|
2917
|
-
[sendRef]
|
|
3252
|
+
[activeSessionId, activeSessionMode, sendRef, customConfirmationSubmit]
|
|
2918
3253
|
);
|
|
2919
3254
|
if (!hasSessions || messages.length === 0 && !streamingMessage) {
|
|
2920
3255
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatThreadEmptyState, {});
|
|
@@ -2928,7 +3263,7 @@ var ChatThread = () => {
|
|
|
2928
3263
|
error,
|
|
2929
3264
|
retryButtonLabel: labels.retryButton,
|
|
2930
3265
|
onRetry: handleRetry,
|
|
2931
|
-
onConfirmationSubmit:
|
|
3266
|
+
onConfirmationSubmit: handleConfirmation,
|
|
2932
3267
|
onQuestionnaireSubmit: handleQuestionnaireSubmit,
|
|
2933
3268
|
renderMessageBlock
|
|
2934
3269
|
}
|
|
@@ -2942,6 +3277,7 @@ var Container = import_styled9.default.div`
|
|
|
2942
3277
|
min-height: 0;
|
|
2943
3278
|
overflow: auto;
|
|
2944
3279
|
padding: 24px;
|
|
3280
|
+
margin-bottom: 24px;
|
|
2945
3281
|
overscroll-behavior: contain;
|
|
2946
3282
|
|
|
2947
3283
|
&::-webkit-scrollbar {
|
|
@@ -4021,6 +4357,27 @@ var StopSpinner = import_styled13.default.span`
|
|
|
4021
4357
|
|
|
4022
4358
|
// src/components/chat-composer/index.tsx
|
|
4023
4359
|
var import_jsx_runtime15 = require("@emotion/react/jsx-runtime");
|
|
4360
|
+
var CHAT_COMPOSER_LINE_HEIGHT_PX = 20;
|
|
4361
|
+
var CHAT_COMPOSER_MAX_ROWS = 7;
|
|
4362
|
+
var CHAT_COMPOSER_PADDING_TOP_PX = 8;
|
|
4363
|
+
var CHAT_COMPOSER_PADDING_BOTTOM_PX = 12;
|
|
4364
|
+
var CHAT_COMPOSER_PADDING_BLOCK_PX = CHAT_COMPOSER_PADDING_TOP_PX + CHAT_COMPOSER_PADDING_BOTTOM_PX;
|
|
4365
|
+
var CHAT_COMPOSER_MIN_ROWS = 4;
|
|
4366
|
+
var CHAT_COMPOSER_EXPANDED_MAX_ROWS = 60;
|
|
4367
|
+
var CHAT_COMPOSER_EXPANDED_MAX_VIEWPORT_RATIO = 0.7;
|
|
4368
|
+
var CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX = 96;
|
|
4369
|
+
var CHAT_COMPOSER_MAX_HEIGHT_PX = CHAT_COMPOSER_MAX_ROWS * CHAT_COMPOSER_LINE_HEIGHT_PX + CHAT_COMPOSER_PADDING_BLOCK_PX;
|
|
4370
|
+
var CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX = CHAT_COMPOSER_EXPANDED_MAX_ROWS * CHAT_COMPOSER_LINE_HEIGHT_PX + CHAT_COMPOSER_PADDING_BLOCK_PX;
|
|
4371
|
+
var getExpandedComposerHeightPx = () => {
|
|
4372
|
+
if (typeof window === "undefined") {
|
|
4373
|
+
return CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX;
|
|
4374
|
+
}
|
|
4375
|
+
const viewportLimitedHeight = window.innerHeight * CHAT_COMPOSER_EXPANDED_MAX_VIEWPORT_RATIO - CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX;
|
|
4376
|
+
return Math.max(
|
|
4377
|
+
CHAT_COMPOSER_MAX_HEIGHT_PX,
|
|
4378
|
+
Math.floor(Math.min(CHAT_COMPOSER_EXPANDED_ROWS_HEIGHT_PX, viewportLimitedHeight))
|
|
4379
|
+
);
|
|
4380
|
+
};
|
|
4024
4381
|
var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4025
4382
|
"svg",
|
|
4026
4383
|
{
|
|
@@ -4033,6 +4390,36 @@ var PlusIcon = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
|
4033
4390
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: "M8 3v10M3 8h10", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" })
|
|
4034
4391
|
}
|
|
4035
4392
|
);
|
|
4393
|
+
var ComposerExpandIcon = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4394
|
+
"svg",
|
|
4395
|
+
{
|
|
4396
|
+
"aria-hidden": "true",
|
|
4397
|
+
width: "16",
|
|
4398
|
+
height: "16",
|
|
4399
|
+
viewBox: "0 0 16 16",
|
|
4400
|
+
fill: "none",
|
|
4401
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
4402
|
+
children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4403
|
+
"path",
|
|
4404
|
+
{
|
|
4405
|
+
d: "M14 6h-4V2M10 6l4-4M2 10h4v4M6 10l-4 4",
|
|
4406
|
+
stroke: "currentColor",
|
|
4407
|
+
strokeWidth: "1.5",
|
|
4408
|
+
strokeLinecap: "round",
|
|
4409
|
+
strokeLinejoin: "round"
|
|
4410
|
+
}
|
|
4411
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4412
|
+
"path",
|
|
4413
|
+
{
|
|
4414
|
+
d: "M10 2h4v4M14 2L9 7M6 14H2v-4M2 14l5-5",
|
|
4415
|
+
stroke: "currentColor",
|
|
4416
|
+
strokeWidth: "1.5",
|
|
4417
|
+
strokeLinecap: "round",
|
|
4418
|
+
strokeLinejoin: "round"
|
|
4419
|
+
}
|
|
4420
|
+
)
|
|
4421
|
+
}
|
|
4422
|
+
);
|
|
4036
4423
|
var ChatComposerView = ({
|
|
4037
4424
|
value,
|
|
4038
4425
|
placeholder,
|
|
@@ -4049,6 +4436,8 @@ var ChatComposerView = ({
|
|
|
4049
4436
|
isStopping,
|
|
4050
4437
|
enableImageAttachments,
|
|
4051
4438
|
modeLabels,
|
|
4439
|
+
expandComposerAriaLabel,
|
|
4440
|
+
collapseComposerAriaLabel,
|
|
4052
4441
|
onValueChange,
|
|
4053
4442
|
onPickImages,
|
|
4054
4443
|
onPasteImages,
|
|
@@ -4060,6 +4449,9 @@ var ChatComposerView = ({
|
|
|
4060
4449
|
onSend
|
|
4061
4450
|
}) => {
|
|
4062
4451
|
const imageInputRef = (0, import_react15.useRef)(null);
|
|
4452
|
+
const inputRef = (0, import_react15.useRef)(null);
|
|
4453
|
+
const [isComposerExpandable, setIsComposerExpandable] = (0, import_react15.useState)(false);
|
|
4454
|
+
const [isComposerExpanded, setIsComposerExpanded] = (0, import_react15.useState)(false);
|
|
4063
4455
|
const canSend = canSendChatMessage({
|
|
4064
4456
|
value,
|
|
4065
4457
|
attachmentCount: attachments.length,
|
|
@@ -4067,6 +4459,26 @@ var ChatComposerView = ({
|
|
|
4067
4459
|
isModelsError,
|
|
4068
4460
|
hasModels
|
|
4069
4461
|
});
|
|
4462
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
4463
|
+
const element = inputRef.current;
|
|
4464
|
+
if (!element) {
|
|
4465
|
+
return;
|
|
4466
|
+
}
|
|
4467
|
+
if (!isComposerExpanded) {
|
|
4468
|
+
element.style.height = "0px";
|
|
4469
|
+
}
|
|
4470
|
+
const scrollHeight = element.scrollHeight;
|
|
4471
|
+
const nextExpandable = scrollHeight > CHAT_COMPOSER_MAX_HEIGHT_PX;
|
|
4472
|
+
const expandedHeight = getExpandedComposerHeightPx();
|
|
4473
|
+
const nextHeight = isComposerExpanded ? expandedHeight : Math.min(scrollHeight, CHAT_COMPOSER_MAX_HEIGHT_PX);
|
|
4474
|
+
setIsComposerExpandable(nextExpandable);
|
|
4475
|
+
element.style.height = `${nextHeight}px`;
|
|
4476
|
+
element.style.overflowY = !isComposerExpanded && scrollHeight > CHAT_COMPOSER_MAX_HEIGHT_PX ? "auto" : "hidden";
|
|
4477
|
+
}, [isComposerExpanded, value]);
|
|
4478
|
+
const handleSend = async () => {
|
|
4479
|
+
setIsComposerExpanded(false);
|
|
4480
|
+
await onSend();
|
|
4481
|
+
};
|
|
4070
4482
|
const handleKeyDown = (event) => {
|
|
4071
4483
|
if (shouldStopChatComposer({ key: event.key, shiftKey: event.shiftKey, isStreaming })) {
|
|
4072
4484
|
event.preventDefault();
|
|
@@ -4076,7 +4488,7 @@ var ChatComposerView = ({
|
|
|
4076
4488
|
if (!shouldSubmitChatComposer({ key: event.key, shiftKey: event.shiftKey, canSend }))
|
|
4077
4489
|
return;
|
|
4078
4490
|
event.preventDefault();
|
|
4079
|
-
void
|
|
4491
|
+
void handleSend();
|
|
4080
4492
|
};
|
|
4081
4493
|
const handlePickImages = (event) => {
|
|
4082
4494
|
if (event.target.files?.length)
|
|
@@ -4111,60 +4523,77 @@ var ChatComposerView = ({
|
|
|
4111
4523
|
}
|
|
4112
4524
|
),
|
|
4113
4525
|
attachmentNotice === "limit_reached" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AttachmentNotice, { "data-testid": "chat-composer-attachment-notice", children: attachmentLimitNotice }) : null,
|
|
4114
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
"data-testid": "chat-composer-input",
|
|
4118
|
-
value,
|
|
4119
|
-
onChange: (event) => onValueChange(event.target.value),
|
|
4120
|
-
onKeyDown: handleKeyDown,
|
|
4121
|
-
onPaste: enableImageAttachments ? handlePaste : void 0,
|
|
4122
|
-
placeholder
|
|
4123
|
-
}
|
|
4124
|
-
),
|
|
4125
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Footer, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Actions2, { "data-testid": "chat-composer-actions", children: [
|
|
4126
|
-
enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4127
|
-
AttachButton,
|
|
4526
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(InputArea, { "data-testid": "chat-composer-input-area", children: [
|
|
4527
|
+
isComposerExpanded || isComposerExpandable ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4528
|
+
ComposerExpandButton,
|
|
4128
4529
|
{
|
|
4129
4530
|
type: "button",
|
|
4130
|
-
"data-testid": "chat-composer-
|
|
4131
|
-
"aria-label":
|
|
4132
|
-
|
|
4133
|
-
|
|
4531
|
+
"data-testid": "chat-composer-expand-toggle",
|
|
4532
|
+
"aria-label": isComposerExpanded ? collapseComposerAriaLabel : expandComposerAriaLabel,
|
|
4533
|
+
"aria-expanded": isComposerExpanded,
|
|
4534
|
+
onClick: () => setIsComposerExpanded((current) => !current),
|
|
4535
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ComposerExpandIcon, { expanded: isComposerExpanded })
|
|
4134
4536
|
}
|
|
4135
4537
|
) : null,
|
|
4136
4538
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4137
|
-
|
|
4138
|
-
{
|
|
4139
|
-
value: selectedMode,
|
|
4140
|
-
disabled: isStreaming,
|
|
4141
|
-
labels: modeLabels,
|
|
4142
|
-
onChange: onSelectedModeChange
|
|
4143
|
-
}
|
|
4144
|
-
),
|
|
4145
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4146
|
-
ChatModelControl,
|
|
4539
|
+
Input,
|
|
4147
4540
|
{
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4541
|
+
ref: inputRef,
|
|
4542
|
+
"data-testid": "chat-composer-input",
|
|
4543
|
+
"data-expanded": isComposerExpanded,
|
|
4544
|
+
value,
|
|
4545
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
4546
|
+
onKeyDown: handleKeyDown,
|
|
4547
|
+
onPaste: enableImageAttachments ? handlePaste : void 0,
|
|
4548
|
+
placeholder
|
|
4155
4549
|
}
|
|
4156
|
-
)
|
|
4157
|
-
|
|
4158
|
-
|
|
4550
|
+
)
|
|
4551
|
+
] }),
|
|
4552
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Footer, { children: [
|
|
4553
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LeadingActions, { "data-testid": "chat-composer-leading-actions", children: enableImageAttachments ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4554
|
+
AttachButton,
|
|
4159
4555
|
{
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4556
|
+
type: "button",
|
|
4557
|
+
"data-testid": "chat-composer-attach-image",
|
|
4558
|
+
"aria-label": "Attach image",
|
|
4559
|
+
onClick: () => imageInputRef.current?.click(),
|
|
4560
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PlusIcon, {})
|
|
4165
4561
|
}
|
|
4166
|
-
)
|
|
4167
|
-
|
|
4562
|
+
) : null }),
|
|
4563
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(TrailingActions, { "data-testid": "chat-composer-trailing-actions", children: [
|
|
4564
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4565
|
+
ChatModeControl,
|
|
4566
|
+
{
|
|
4567
|
+
value: selectedMode,
|
|
4568
|
+
disabled: isStreaming,
|
|
4569
|
+
labels: modeLabels,
|
|
4570
|
+
onChange: onSelectedModeChange
|
|
4571
|
+
}
|
|
4572
|
+
),
|
|
4573
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4574
|
+
ChatModelControl,
|
|
4575
|
+
{
|
|
4576
|
+
selectedModel,
|
|
4577
|
+
availableModels,
|
|
4578
|
+
isModelsLoading,
|
|
4579
|
+
isModelsError,
|
|
4580
|
+
hasModels,
|
|
4581
|
+
onSelectedModelChange,
|
|
4582
|
+
onReloadModels
|
|
4583
|
+
}
|
|
4584
|
+
),
|
|
4585
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
4586
|
+
ChatSendActions,
|
|
4587
|
+
{
|
|
4588
|
+
canSend,
|
|
4589
|
+
isStreaming,
|
|
4590
|
+
isStopping,
|
|
4591
|
+
onStop,
|
|
4592
|
+
onSend: handleSend
|
|
4593
|
+
}
|
|
4594
|
+
)
|
|
4595
|
+
] })
|
|
4596
|
+
] })
|
|
4168
4597
|
] }) });
|
|
4169
4598
|
};
|
|
4170
4599
|
var ChatComposer = () => {
|
|
@@ -4200,6 +4629,8 @@ var ChatComposer = () => {
|
|
|
4200
4629
|
isStopping: state.isStopping,
|
|
4201
4630
|
enableImageAttachments,
|
|
4202
4631
|
modeLabels,
|
|
4632
|
+
expandComposerAriaLabel: labels.expandComposerAriaLabel,
|
|
4633
|
+
collapseComposerAriaLabel: labels.collapseComposerAriaLabel,
|
|
4203
4634
|
onValueChange: actions.setValue,
|
|
4204
4635
|
onPickImages: actions.pickImages,
|
|
4205
4636
|
onPasteImages: actions.pasteImages,
|
|
@@ -4216,6 +4647,16 @@ var Container2 = import_styled14.default.div`
|
|
|
4216
4647
|
padding: 0 16px 16px;
|
|
4217
4648
|
`;
|
|
4218
4649
|
var Surface = import_styled14.default.div`
|
|
4650
|
+
display: grid;
|
|
4651
|
+
grid-template-columns: minmax(0, 1fr);
|
|
4652
|
+
grid-template-areas:
|
|
4653
|
+
'attachments'
|
|
4654
|
+
'notice'
|
|
4655
|
+
'input'
|
|
4656
|
+
'footer';
|
|
4657
|
+
width: 100%;
|
|
4658
|
+
max-width: 760px;
|
|
4659
|
+
margin: 0 auto;
|
|
4219
4660
|
background: var(--border-color);
|
|
4220
4661
|
border-radius: 20px;
|
|
4221
4662
|
border: 1px solid var(--border-hover);
|
|
@@ -4225,6 +4666,7 @@ var Surface = import_styled14.default.div`
|
|
|
4225
4666
|
backdrop-filter: blur(10px);
|
|
4226
4667
|
`;
|
|
4227
4668
|
var AttachmentNotice = import_styled14.default.div`
|
|
4669
|
+
grid-area: notice;
|
|
4228
4670
|
margin: 10px 12px 0;
|
|
4229
4671
|
padding: 8px 10px;
|
|
4230
4672
|
border-radius: 10px;
|
|
@@ -4234,19 +4676,45 @@ var AttachmentNotice = import_styled14.default.div`
|
|
|
4234
4676
|
font-size: 12px;
|
|
4235
4677
|
line-height: 1.4;
|
|
4236
4678
|
`;
|
|
4679
|
+
var InputArea = import_styled14.default.div`
|
|
4680
|
+
grid-area: input;
|
|
4681
|
+
position: relative;
|
|
4682
|
+
`;
|
|
4237
4683
|
var Input = import_styled14.default.textarea`
|
|
4684
|
+
--textarea-line-height: ${CHAT_COMPOSER_LINE_HEIGHT_PX}px;
|
|
4685
|
+
--textarea-min-rows: ${CHAT_COMPOSER_MIN_ROWS};
|
|
4686
|
+
--textarea-max-rows: ${CHAT_COMPOSER_MAX_ROWS};
|
|
4687
|
+
--textarea-expanded-max-rows: ${CHAT_COMPOSER_EXPANDED_MAX_ROWS};
|
|
4688
|
+
--textarea-padding-top: ${CHAT_COMPOSER_PADDING_TOP_PX}px;
|
|
4689
|
+
--textarea-padding-bottom: ${CHAT_COMPOSER_PADDING_BOTTOM_PX}px;
|
|
4690
|
+
--textarea-padding-block: calc(var(--textarea-padding-top) + var(--textarea-padding-bottom));
|
|
4691
|
+
--textarea-max-height: calc(
|
|
4692
|
+
var(--textarea-max-rows) * var(--textarea-line-height) + var(--textarea-padding-block)
|
|
4693
|
+
);
|
|
4694
|
+
--textarea-expanded-max-height: min(
|
|
4695
|
+
calc(
|
|
4696
|
+
var(--textarea-expanded-max-rows) * var(--textarea-line-height) +
|
|
4697
|
+
var(--textarea-padding-block)
|
|
4698
|
+
),
|
|
4699
|
+
calc(70vh - ${CHAT_COMPOSER_EXPANDED_RESERVED_SPACE_PX}px)
|
|
4700
|
+
);
|
|
4238
4701
|
width: 100%;
|
|
4239
|
-
min-height:
|
|
4702
|
+
min-height: calc(
|
|
4703
|
+
var(--textarea-min-rows) * var(--textarea-line-height) + var(--textarea-padding-block)
|
|
4704
|
+
);
|
|
4705
|
+
max-height: var(--textarea-max-height);
|
|
4706
|
+
box-sizing: border-box;
|
|
4240
4707
|
resize: none;
|
|
4241
4708
|
appearance: none;
|
|
4242
4709
|
border: 0;
|
|
4243
4710
|
outline: 0;
|
|
4244
4711
|
background: transparent;
|
|
4245
|
-
padding:
|
|
4712
|
+
padding: var(--textarea-padding-top) 44px var(--textarea-padding-bottom) 12px;
|
|
4246
4713
|
font-weight: 400;
|
|
4247
4714
|
font-size: 14px;
|
|
4248
4715
|
color: var(--text-primary);
|
|
4249
|
-
line-height:
|
|
4716
|
+
line-height: var(--textarea-line-height);
|
|
4717
|
+
overflow-y: hidden;
|
|
4250
4718
|
|
|
4251
4719
|
&::placeholder {
|
|
4252
4720
|
color: var(--text-secondary);
|
|
@@ -4255,19 +4723,50 @@ var Input = import_styled14.default.textarea`
|
|
|
4255
4723
|
&::-webkit-resizer {
|
|
4256
4724
|
display: none;
|
|
4257
4725
|
}
|
|
4726
|
+
|
|
4727
|
+
&[data-expanded='true'] {
|
|
4728
|
+
max-height: var(--textarea-expanded-max-height);
|
|
4729
|
+
}
|
|
4730
|
+
`;
|
|
4731
|
+
var ComposerExpandButton = import_styled14.default.button`
|
|
4732
|
+
position: absolute;
|
|
4733
|
+
top: 8px;
|
|
4734
|
+
right: 10px;
|
|
4735
|
+
width: 28px;
|
|
4736
|
+
height: 28px;
|
|
4737
|
+
display: grid;
|
|
4738
|
+
place-items: center;
|
|
4739
|
+
border: none;
|
|
4740
|
+
border-radius: 999px;
|
|
4741
|
+
background: transparent;
|
|
4742
|
+
color: rgba(255, 255, 255, 0.72);
|
|
4743
|
+
cursor: pointer;
|
|
4744
|
+
z-index: 1;
|
|
4745
|
+
|
|
4746
|
+
&:hover {
|
|
4747
|
+
background: rgba(255, 255, 255, 0.08);
|
|
4748
|
+
color: rgba(255, 255, 255, 0.92);
|
|
4749
|
+
}
|
|
4258
4750
|
`;
|
|
4259
4751
|
var Footer = import_styled14.default.div`
|
|
4260
|
-
|
|
4752
|
+
grid-area: footer;
|
|
4753
|
+
display: grid;
|
|
4754
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
4261
4755
|
align-items: flex-end;
|
|
4262
|
-
justify-content: stretch;
|
|
4263
4756
|
gap: 16px;
|
|
4264
4757
|
padding: 0 14px 14px;
|
|
4265
4758
|
`;
|
|
4266
|
-
var
|
|
4759
|
+
var LeadingActions = import_styled14.default.div`
|
|
4760
|
+
display: flex;
|
|
4761
|
+
align-items: center;
|
|
4762
|
+
justify-content: flex-start;
|
|
4763
|
+
gap: 8px;
|
|
4764
|
+
min-width: 0;
|
|
4765
|
+
`;
|
|
4766
|
+
var TrailingActions = import_styled14.default.div`
|
|
4267
4767
|
display: flex;
|
|
4268
4768
|
align-items: center;
|
|
4269
4769
|
flex-wrap: wrap;
|
|
4270
|
-
width: 100%;
|
|
4271
4770
|
min-width: 0;
|
|
4272
4771
|
justify-content: flex-end;
|
|
4273
4772
|
gap: 8px;
|