@hef2024/llmasaservice-ui 0.23.2 → 0.24.1
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.css +284 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +86 -30
- package/dist/index.mjs +86 -30
- package/package.json +1 -1
- package/src/AIChatPanel.css +178 -0
- package/src/AIChatPanel.tsx +30 -20
- package/src/ChatPanel.css +178 -0
- package/src/ChatPanel.tsx +89 -21
- package/src/components/ui/ThinkingBlock.tsx +22 -8
package/dist/index.css
CHANGED
|
@@ -1114,6 +1114,23 @@ button[data-pending=true]::after {
|
|
|
1114
1114
|
align-items: center;
|
|
1115
1115
|
gap: 8px;
|
|
1116
1116
|
}
|
|
1117
|
+
.thinking-block__icon-wrapper {
|
|
1118
|
+
display: flex;
|
|
1119
|
+
align-items: center;
|
|
1120
|
+
justify-content: center;
|
|
1121
|
+
flex-shrink: 0;
|
|
1122
|
+
}
|
|
1123
|
+
.thinking-block__icon-wrapper--spinning {
|
|
1124
|
+
animation: thinkingIconSpin 1.5s linear infinite;
|
|
1125
|
+
}
|
|
1126
|
+
@keyframes thinkingIconSpin {
|
|
1127
|
+
from {
|
|
1128
|
+
transform: rotate(0deg);
|
|
1129
|
+
}
|
|
1130
|
+
to {
|
|
1131
|
+
transform: rotate(360deg);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1117
1134
|
.thinking-block__icon {
|
|
1118
1135
|
width: 16px;
|
|
1119
1136
|
height: 16px;
|
|
@@ -1124,6 +1141,30 @@ button[data-pending=true]::after {
|
|
|
1124
1141
|
font-weight: 600;
|
|
1125
1142
|
font-size: 13px;
|
|
1126
1143
|
color: var(--thinking-block-text, var(--title-text-color));
|
|
1144
|
+
position: relative;
|
|
1145
|
+
}
|
|
1146
|
+
.thinking-block__title--shimmer {
|
|
1147
|
+
background:
|
|
1148
|
+
linear-gradient(
|
|
1149
|
+
90deg,
|
|
1150
|
+
var(--thinking-block-text, var(--title-text-color)) 0%,
|
|
1151
|
+
var(--thinking-block-text, var(--title-text-color)) 40%,
|
|
1152
|
+
var(--thinking-block-accent, var(--ai-chat-thinking-icon)) 50%,
|
|
1153
|
+
var(--thinking-block-text, var(--title-text-color)) 60%,
|
|
1154
|
+
var(--thinking-block-text, var(--title-text-color)) 100%);
|
|
1155
|
+
background-size: 200% 100%;
|
|
1156
|
+
-webkit-background-clip: text;
|
|
1157
|
+
background-clip: text;
|
|
1158
|
+
-webkit-text-fill-color: transparent;
|
|
1159
|
+
animation: titleShimmer 2s ease-in-out infinite;
|
|
1160
|
+
}
|
|
1161
|
+
@keyframes titleShimmer {
|
|
1162
|
+
0% {
|
|
1163
|
+
background-position: 100% 0;
|
|
1164
|
+
}
|
|
1165
|
+
100% {
|
|
1166
|
+
background-position: -100% 0;
|
|
1167
|
+
}
|
|
1127
1168
|
}
|
|
1128
1169
|
.thinking-block__chevron {
|
|
1129
1170
|
width: 16px;
|
|
@@ -1295,6 +1336,107 @@ button[data-pending=true]::after {
|
|
|
1295
1336
|
.thinking-block:not(.thinking-block--collapsed) {
|
|
1296
1337
|
border-left-width: 3px;
|
|
1297
1338
|
}
|
|
1339
|
+
.thinking-block--collapsed {
|
|
1340
|
+
margin-bottom: 4px;
|
|
1341
|
+
border-radius: 6px;
|
|
1342
|
+
border-width: 0;
|
|
1343
|
+
background-color: transparent;
|
|
1344
|
+
}
|
|
1345
|
+
.thinking-block--collapsed .thinking-block__header {
|
|
1346
|
+
padding: 4px 8px;
|
|
1347
|
+
}
|
|
1348
|
+
.thinking-block--collapsed .thinking-block__header-left {
|
|
1349
|
+
gap: 6px;
|
|
1350
|
+
flex: 1;
|
|
1351
|
+
min-width: 0;
|
|
1352
|
+
}
|
|
1353
|
+
.thinking-block--collapsed .thinking-block__icon-wrapper {
|
|
1354
|
+
flex-shrink: 0;
|
|
1355
|
+
}
|
|
1356
|
+
.thinking-block--collapsed .thinking-block__icon {
|
|
1357
|
+
width: 14px;
|
|
1358
|
+
height: 14px;
|
|
1359
|
+
opacity: 0.6;
|
|
1360
|
+
}
|
|
1361
|
+
.thinking-block--collapsed .thinking-block__title {
|
|
1362
|
+
font-size: 12px;
|
|
1363
|
+
font-weight: 500;
|
|
1364
|
+
opacity: 0.7;
|
|
1365
|
+
flex-shrink: 0;
|
|
1366
|
+
}
|
|
1367
|
+
.thinking-block__preview {
|
|
1368
|
+
font-size: 11px;
|
|
1369
|
+
font-weight: 400;
|
|
1370
|
+
opacity: 0.5;
|
|
1371
|
+
color: var(--thinking-block-text, var(--title-text-color));
|
|
1372
|
+
white-space: nowrap;
|
|
1373
|
+
overflow: hidden;
|
|
1374
|
+
text-overflow: ellipsis;
|
|
1375
|
+
flex: 1;
|
|
1376
|
+
min-width: 0;
|
|
1377
|
+
}
|
|
1378
|
+
.thinking-block--collapsed .thinking-block__chevron {
|
|
1379
|
+
width: 12px;
|
|
1380
|
+
height: 12px;
|
|
1381
|
+
opacity: 0.4;
|
|
1382
|
+
flex-shrink: 0;
|
|
1383
|
+
}
|
|
1384
|
+
.thinking-block--collapsed:hover {
|
|
1385
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
1386
|
+
}
|
|
1387
|
+
.thinking-block--collapsed:hover .thinking-block__icon,
|
|
1388
|
+
.thinking-block--collapsed:hover .thinking-block__title {
|
|
1389
|
+
opacity: 0.9;
|
|
1390
|
+
}
|
|
1391
|
+
.thinking-block--collapsed:hover .thinking-block__preview {
|
|
1392
|
+
opacity: 0.7;
|
|
1393
|
+
}
|
|
1394
|
+
.thinking-block--collapsed:hover .thinking-block__chevron {
|
|
1395
|
+
opacity: 0.6;
|
|
1396
|
+
}
|
|
1397
|
+
.dark-theme .thinking-block--collapsed:hover {
|
|
1398
|
+
background-color: rgba(255, 255, 255, 0.06);
|
|
1399
|
+
}
|
|
1400
|
+
.thinking-block:not(.thinking-block--collapsed) {
|
|
1401
|
+
margin-bottom: 8px;
|
|
1402
|
+
border-radius: 6px;
|
|
1403
|
+
border: none;
|
|
1404
|
+
background-color: transparent;
|
|
1405
|
+
opacity: 0.75;
|
|
1406
|
+
}
|
|
1407
|
+
.thinking-block:not(.thinking-block--collapsed):hover {
|
|
1408
|
+
opacity: 0.9;
|
|
1409
|
+
}
|
|
1410
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__header {
|
|
1411
|
+
padding: 4px 10px;
|
|
1412
|
+
}
|
|
1413
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__icon {
|
|
1414
|
+
width: 14px;
|
|
1415
|
+
height: 14px;
|
|
1416
|
+
opacity: 0.7;
|
|
1417
|
+
}
|
|
1418
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__title {
|
|
1419
|
+
font-size: 12px;
|
|
1420
|
+
opacity: 0.8;
|
|
1421
|
+
}
|
|
1422
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__chevron {
|
|
1423
|
+
opacity: 0.5;
|
|
1424
|
+
}
|
|
1425
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__content {
|
|
1426
|
+
padding: 0 10px 6px 10px;
|
|
1427
|
+
font-size: 11px;
|
|
1428
|
+
line-height: 1.5;
|
|
1429
|
+
opacity: 0.7;
|
|
1430
|
+
max-height: 120px;
|
|
1431
|
+
overflow-y: auto;
|
|
1432
|
+
}
|
|
1433
|
+
.thinking-block--streaming:not(.thinking-block--collapsed) {
|
|
1434
|
+
opacity: 0.85;
|
|
1435
|
+
background-color: rgba(0, 0, 0, 0.015);
|
|
1436
|
+
}
|
|
1437
|
+
.dark-theme .thinking-block--streaming:not(.thinking-block--collapsed) {
|
|
1438
|
+
background-color: rgba(255, 255, 255, 0.02);
|
|
1439
|
+
}
|
|
1298
1440
|
.thinking-block {
|
|
1299
1441
|
animation: thinkingBlockAppear 0.2s ease-out;
|
|
1300
1442
|
}
|
|
@@ -4457,6 +4599,23 @@ button[data-pending=true]::after {
|
|
|
4457
4599
|
align-items: center;
|
|
4458
4600
|
gap: 8px;
|
|
4459
4601
|
}
|
|
4602
|
+
.thinking-block__icon-wrapper {
|
|
4603
|
+
display: flex;
|
|
4604
|
+
align-items: center;
|
|
4605
|
+
justify-content: center;
|
|
4606
|
+
flex-shrink: 0;
|
|
4607
|
+
}
|
|
4608
|
+
.thinking-block__icon-wrapper--spinning {
|
|
4609
|
+
animation: thinkingIconSpin 1.5s linear infinite;
|
|
4610
|
+
}
|
|
4611
|
+
@keyframes thinkingIconSpin {
|
|
4612
|
+
from {
|
|
4613
|
+
transform: rotate(0deg);
|
|
4614
|
+
}
|
|
4615
|
+
to {
|
|
4616
|
+
transform: rotate(360deg);
|
|
4617
|
+
}
|
|
4618
|
+
}
|
|
4460
4619
|
.thinking-block__icon {
|
|
4461
4620
|
width: 16px;
|
|
4462
4621
|
height: 16px;
|
|
@@ -4467,6 +4626,30 @@ button[data-pending=true]::after {
|
|
|
4467
4626
|
font-weight: 600;
|
|
4468
4627
|
font-size: 13px;
|
|
4469
4628
|
color: var(--thinking-block-text, var(--ai-chat-thinking-text));
|
|
4629
|
+
position: relative;
|
|
4630
|
+
}
|
|
4631
|
+
.thinking-block__title--shimmer {
|
|
4632
|
+
background:
|
|
4633
|
+
linear-gradient(
|
|
4634
|
+
90deg,
|
|
4635
|
+
var(--thinking-block-text, var(--ai-chat-thinking-text)) 0%,
|
|
4636
|
+
var(--thinking-block-text, var(--ai-chat-thinking-text)) 40%,
|
|
4637
|
+
var(--thinking-block-accent, var(--ai-chat-thinking-icon)) 50%,
|
|
4638
|
+
var(--thinking-block-text, var(--ai-chat-thinking-text)) 60%,
|
|
4639
|
+
var(--thinking-block-text, var(--ai-chat-thinking-text)) 100%);
|
|
4640
|
+
background-size: 200% 100%;
|
|
4641
|
+
-webkit-background-clip: text;
|
|
4642
|
+
background-clip: text;
|
|
4643
|
+
-webkit-text-fill-color: transparent;
|
|
4644
|
+
animation: titleShimmer 2s ease-in-out infinite;
|
|
4645
|
+
}
|
|
4646
|
+
@keyframes titleShimmer {
|
|
4647
|
+
0% {
|
|
4648
|
+
background-position: 100% 0;
|
|
4649
|
+
}
|
|
4650
|
+
100% {
|
|
4651
|
+
background-position: -100% 0;
|
|
4652
|
+
}
|
|
4470
4653
|
}
|
|
4471
4654
|
.thinking-block__chevron {
|
|
4472
4655
|
width: 16px;
|
|
@@ -4638,6 +4821,107 @@ button[data-pending=true]::after {
|
|
|
4638
4821
|
.thinking-block:not(.thinking-block--collapsed) {
|
|
4639
4822
|
border-left-width: 3px;
|
|
4640
4823
|
}
|
|
4824
|
+
.thinking-block--collapsed {
|
|
4825
|
+
margin-bottom: 4px;
|
|
4826
|
+
border-radius: 6px;
|
|
4827
|
+
border-width: 0;
|
|
4828
|
+
background-color: transparent;
|
|
4829
|
+
}
|
|
4830
|
+
.thinking-block--collapsed .thinking-block__header {
|
|
4831
|
+
padding: 4px 8px;
|
|
4832
|
+
}
|
|
4833
|
+
.thinking-block--collapsed .thinking-block__header-left {
|
|
4834
|
+
gap: 6px;
|
|
4835
|
+
flex: 1;
|
|
4836
|
+
min-width: 0;
|
|
4837
|
+
}
|
|
4838
|
+
.thinking-block--collapsed .thinking-block__icon-wrapper {
|
|
4839
|
+
flex-shrink: 0;
|
|
4840
|
+
}
|
|
4841
|
+
.thinking-block--collapsed .thinking-block__icon {
|
|
4842
|
+
width: 14px;
|
|
4843
|
+
height: 14px;
|
|
4844
|
+
opacity: 0.6;
|
|
4845
|
+
}
|
|
4846
|
+
.thinking-block--collapsed .thinking-block__title {
|
|
4847
|
+
font-size: 12px;
|
|
4848
|
+
font-weight: 500;
|
|
4849
|
+
opacity: 0.7;
|
|
4850
|
+
flex-shrink: 0;
|
|
4851
|
+
}
|
|
4852
|
+
.thinking-block__preview {
|
|
4853
|
+
font-size: 11px;
|
|
4854
|
+
font-weight: 400;
|
|
4855
|
+
opacity: 0.5;
|
|
4856
|
+
color: var(--thinking-block-text, var(--ai-chat-thinking-text));
|
|
4857
|
+
white-space: nowrap;
|
|
4858
|
+
overflow: hidden;
|
|
4859
|
+
text-overflow: ellipsis;
|
|
4860
|
+
flex: 1;
|
|
4861
|
+
min-width: 0;
|
|
4862
|
+
}
|
|
4863
|
+
.thinking-block--collapsed .thinking-block__chevron {
|
|
4864
|
+
width: 12px;
|
|
4865
|
+
height: 12px;
|
|
4866
|
+
opacity: 0.4;
|
|
4867
|
+
flex-shrink: 0;
|
|
4868
|
+
}
|
|
4869
|
+
.thinking-block--collapsed:hover {
|
|
4870
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
4871
|
+
}
|
|
4872
|
+
.thinking-block--collapsed:hover .thinking-block__icon,
|
|
4873
|
+
.thinking-block--collapsed:hover .thinking-block__title {
|
|
4874
|
+
opacity: 0.9;
|
|
4875
|
+
}
|
|
4876
|
+
.thinking-block--collapsed:hover .thinking-block__preview {
|
|
4877
|
+
opacity: 0.7;
|
|
4878
|
+
}
|
|
4879
|
+
.thinking-block--collapsed:hover .thinking-block__chevron {
|
|
4880
|
+
opacity: 0.6;
|
|
4881
|
+
}
|
|
4882
|
+
.dark-theme .thinking-block--collapsed:hover {
|
|
4883
|
+
background-color: rgba(255, 255, 255, 0.06);
|
|
4884
|
+
}
|
|
4885
|
+
.thinking-block:not(.thinking-block--collapsed) {
|
|
4886
|
+
margin-bottom: 8px;
|
|
4887
|
+
border-radius: 6px;
|
|
4888
|
+
border: none;
|
|
4889
|
+
background-color: transparent;
|
|
4890
|
+
opacity: 0.75;
|
|
4891
|
+
}
|
|
4892
|
+
.thinking-block:not(.thinking-block--collapsed):hover {
|
|
4893
|
+
opacity: 0.9;
|
|
4894
|
+
}
|
|
4895
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__header {
|
|
4896
|
+
padding: 4px 10px;
|
|
4897
|
+
}
|
|
4898
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__icon {
|
|
4899
|
+
width: 14px;
|
|
4900
|
+
height: 14px;
|
|
4901
|
+
opacity: 0.7;
|
|
4902
|
+
}
|
|
4903
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__title {
|
|
4904
|
+
font-size: 12px;
|
|
4905
|
+
opacity: 0.8;
|
|
4906
|
+
}
|
|
4907
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__chevron {
|
|
4908
|
+
opacity: 0.5;
|
|
4909
|
+
}
|
|
4910
|
+
.thinking-block:not(.thinking-block--collapsed) .thinking-block__content {
|
|
4911
|
+
padding: 0 10px 6px 10px;
|
|
4912
|
+
font-size: 11px;
|
|
4913
|
+
line-height: 1.5;
|
|
4914
|
+
opacity: 0.7;
|
|
4915
|
+
max-height: 120px;
|
|
4916
|
+
overflow-y: auto;
|
|
4917
|
+
}
|
|
4918
|
+
.thinking-block--streaming:not(.thinking-block--collapsed) {
|
|
4919
|
+
opacity: 0.85;
|
|
4920
|
+
background-color: rgba(0, 0, 0, 0.015);
|
|
4921
|
+
}
|
|
4922
|
+
.dark-theme .thinking-block--streaming:not(.thinking-block--collapsed) {
|
|
4923
|
+
background-color: rgba(255, 255, 255, 0.02);
|
|
4924
|
+
}
|
|
4641
4925
|
.thinking-block {
|
|
4642
4926
|
animation: thinkingBlockAppear 0.2s ease-out;
|
|
4643
4927
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -596,6 +596,11 @@ interface ThinkingBlockProps {
|
|
|
596
596
|
/**
|
|
597
597
|
* ThinkingBlock - A collapsible block for displaying thinking/reasoning/searching content
|
|
598
598
|
* with streaming support. Content streams in naturally as it arrives.
|
|
599
|
+
*
|
|
600
|
+
* Features Cursor-style effects:
|
|
601
|
+
* - Spinning icon when streaming
|
|
602
|
+
* - Shimmer highlight effect on title text
|
|
603
|
+
* - Compact collapsed state with content preview
|
|
599
604
|
*/
|
|
600
605
|
declare const ThinkingBlock: React__default.FC<ThinkingBlockProps>;
|
|
601
606
|
|
package/dist/index.d.ts
CHANGED
|
@@ -596,6 +596,11 @@ interface ThinkingBlockProps {
|
|
|
596
596
|
/**
|
|
597
597
|
* ThinkingBlock - A collapsible block for displaying thinking/reasoning/searching content
|
|
598
598
|
* with streaming support. Content streams in naturally as it arrives.
|
|
599
|
+
*
|
|
600
|
+
* Features Cursor-style effects:
|
|
601
|
+
* - Spinning icon when streaming
|
|
602
|
+
* - Shimmer highlight effect on title text
|
|
603
|
+
* - Compact collapsed state with content preview
|
|
599
604
|
*/
|
|
600
605
|
declare const ThinkingBlock: React__default.FC<ThinkingBlockProps>;
|
|
601
606
|
|
package/dist/index.js
CHANGED
|
@@ -668,10 +668,15 @@ var ThinkingBlock = ({
|
|
|
668
668
|
}) => {
|
|
669
669
|
const displayTitle = title || getDefaultTitle(type);
|
|
670
670
|
const icon = getIcon(type);
|
|
671
|
+
const getPreview = (text, maxLength = 60) => {
|
|
672
|
+
const cleaned = text.replace(/\s+/g, " ").trim();
|
|
673
|
+
if (cleaned.length <= maxLength) return cleaned;
|
|
674
|
+
return cleaned.substring(0, maxLength).trim() + "...";
|
|
675
|
+
};
|
|
671
676
|
return /* @__PURE__ */ import_react10.default.createElement(
|
|
672
677
|
"div",
|
|
673
678
|
{
|
|
674
|
-
className: `thinking-block thinking-block--${type} ${isCollapsed ? "thinking-block--collapsed" : ""}`
|
|
679
|
+
className: `thinking-block thinking-block--${type} ${isCollapsed ? "thinking-block--collapsed" : ""} ${isStreaming ? "thinking-block--streaming" : ""}`
|
|
675
680
|
},
|
|
676
681
|
/* @__PURE__ */ import_react10.default.createElement(
|
|
677
682
|
"button",
|
|
@@ -681,7 +686,7 @@ var ThinkingBlock = ({
|
|
|
681
686
|
type: "button",
|
|
682
687
|
"aria-expanded": !isCollapsed
|
|
683
688
|
},
|
|
684
|
-
/* @__PURE__ */ import_react10.default.createElement("div", { className: "thinking-block__header-left" },
|
|
689
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "thinking-block__header-left" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: `thinking-block__icon-wrapper ${isStreaming ? "thinking-block__icon-wrapper--spinning" : ""}` }, icon), /* @__PURE__ */ import_react10.default.createElement("span", { className: `thinking-block__title ${isStreaming ? "thinking-block__title--shimmer" : ""}` }, displayTitle), isCollapsed && content && /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__preview" }, getPreview(content))),
|
|
685
690
|
/* @__PURE__ */ import_react10.default.createElement(ChevronIcon, { isCollapsed })
|
|
686
691
|
),
|
|
687
692
|
/* @__PURE__ */ import_react10.default.createElement("div", { className: "thinking-block__content-wrapper" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "thinking-block__content" }, content, isStreaming && /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__cursor" }, "|")))
|
|
@@ -842,6 +847,11 @@ var ChatPanel = ({
|
|
|
842
847
|
}, []);
|
|
843
848
|
const [iframeUrl, setIframeUrl] = (0, import_react11.useState)(null);
|
|
844
849
|
const responseAreaRef = (0, import_react11.useRef)(null);
|
|
850
|
+
const [userHasScrolled, setUserHasScrolled] = (0, import_react11.useState)(false);
|
|
851
|
+
const lastScrollTopRef = (0, import_react11.useRef)(0);
|
|
852
|
+
const prevResponseLengthRef = (0, import_react11.useRef)(0);
|
|
853
|
+
const userHasScrolledRef = (0, import_react11.useRef)(false);
|
|
854
|
+
const idleRef = (0, import_react11.useRef)(true);
|
|
845
855
|
const THINKING_PATTERNS = (0, import_react11.useMemo)(
|
|
846
856
|
() => ({
|
|
847
857
|
thinking: /<thinking>([\s\S]*?)<\/thinking>/gi,
|
|
@@ -2174,32 +2184,67 @@ var ChatPanel = ({
|
|
|
2174
2184
|
}
|
|
2175
2185
|
}
|
|
2176
2186
|
}, [initialPrompt]);
|
|
2187
|
+
(0, import_react11.useEffect)(() => {
|
|
2188
|
+
userHasScrolledRef.current = userHasScrolled;
|
|
2189
|
+
}, [userHasScrolled]);
|
|
2190
|
+
(0, import_react11.useEffect)(() => {
|
|
2191
|
+
idleRef.current = idle;
|
|
2192
|
+
}, [idle]);
|
|
2177
2193
|
(0, import_react11.useEffect)(() => {
|
|
2178
2194
|
var _a2;
|
|
2179
|
-
if (
|
|
2195
|
+
if (idle) return;
|
|
2196
|
+
const currentResponseLength = response.length;
|
|
2197
|
+
const responseGotLonger = currentResponseLength > prevResponseLengthRef.current;
|
|
2198
|
+
prevResponseLengthRef.current = currentResponseLength;
|
|
2199
|
+
const shouldAutoScroll = scrollToEnd || !userHasScrolledRef.current;
|
|
2200
|
+
if (shouldAutoScroll && response && responseGotLonger) {
|
|
2180
2201
|
if (window.top !== window.self) {
|
|
2181
2202
|
const responseArea = responseAreaRef.current;
|
|
2182
|
-
responseArea
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2203
|
+
if (responseArea) {
|
|
2204
|
+
responseArea.scrollTo({
|
|
2205
|
+
top: responseArea.scrollHeight,
|
|
2206
|
+
behavior: "auto"
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2186
2209
|
} else {
|
|
2187
|
-
(_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "
|
|
2210
|
+
(_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "auto", block: "end" });
|
|
2188
2211
|
}
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
responseArea.addEventListener("scroll", handleScroll);
|
|
2199
|
-
return () => responseArea.removeEventListener("scroll", handleScroll);
|
|
2212
|
+
}
|
|
2213
|
+
}, [response, idle, scrollToEnd]);
|
|
2214
|
+
(0, import_react11.useEffect)(() => {
|
|
2215
|
+
const responseArea = responseAreaRef.current;
|
|
2216
|
+
if (!responseArea) return;
|
|
2217
|
+
const handleWheel = (e) => {
|
|
2218
|
+
if (idleRef.current) return;
|
|
2219
|
+
if (e.deltaY < 0 && !userHasScrolledRef.current) {
|
|
2220
|
+
setUserHasScrolled(true);
|
|
2200
2221
|
}
|
|
2222
|
+
};
|
|
2223
|
+
const handleScroll = () => {
|
|
2224
|
+
setHasScroll(hasVerticalScrollbar(responseArea));
|
|
2225
|
+
const isScrolledToBottom = responseArea.scrollHeight - responseArea.scrollTop - responseArea.clientHeight < 5;
|
|
2226
|
+
setIsAtBottom(isScrolledToBottom);
|
|
2227
|
+
if (!idleRef.current && userHasScrolledRef.current) {
|
|
2228
|
+
const isNearBottom = responseArea.scrollHeight - responseArea.scrollTop - responseArea.clientHeight < 50;
|
|
2229
|
+
if (isNearBottom) {
|
|
2230
|
+
setUserHasScrolled(false);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
};
|
|
2234
|
+
handleScroll();
|
|
2235
|
+
responseArea.addEventListener("wheel", handleWheel, { passive: true });
|
|
2236
|
+
responseArea.addEventListener("scroll", handleScroll, { passive: true });
|
|
2237
|
+
return () => {
|
|
2238
|
+
responseArea.removeEventListener("wheel", handleWheel);
|
|
2239
|
+
responseArea.removeEventListener("scroll", handleScroll);
|
|
2240
|
+
};
|
|
2241
|
+
}, []);
|
|
2242
|
+
(0, import_react11.useEffect)(() => {
|
|
2243
|
+
const responseArea = responseAreaRef.current;
|
|
2244
|
+
if (responseArea) {
|
|
2245
|
+
setHasScroll(hasVerticalScrollbar(responseArea));
|
|
2201
2246
|
}
|
|
2202
|
-
}, [
|
|
2247
|
+
}, [history]);
|
|
2203
2248
|
(0, import_react11.useEffect)(() => {
|
|
2204
2249
|
if (historyCallbackRef.current) {
|
|
2205
2250
|
historyCallbackRef.current(history);
|
|
@@ -2322,6 +2367,8 @@ var ChatPanel = ({
|
|
|
2322
2367
|
hasAutoCollapsedRef.current = false;
|
|
2323
2368
|
prevBlockCountRef.current = 0;
|
|
2324
2369
|
setError(null);
|
|
2370
|
+
setUserHasScrolled(false);
|
|
2371
|
+
prevResponseLengthRef.current = 0;
|
|
2325
2372
|
setResponse("");
|
|
2326
2373
|
if (emailInput && isEmailAddress(emailInput) && !emailInputSet) {
|
|
2327
2374
|
const newId = (currentCustomer == null ? void 0 : currentCustomer.customer_id) && currentCustomer.customer_id !== "" && currentCustomer.customer_id !== (currentCustomer == null ? void 0 : currentCustomer.customer_user_email) ? currentCustomer.customer_id : emailInput;
|
|
@@ -4655,7 +4702,7 @@ var AIChatPanel = ({
|
|
|
4655
4702
|
cancelAnimationFrame(scrollRAFRef.current);
|
|
4656
4703
|
}
|
|
4657
4704
|
if (!force && responseAreaRef.current) {
|
|
4658
|
-
const scrollViewport = responseAreaRef.current.querySelector("
|
|
4705
|
+
const scrollViewport = responseAreaRef.current.querySelector(".ai-scroll-area-viewport");
|
|
4659
4706
|
const scrollElement = scrollViewport || responseAreaRef.current;
|
|
4660
4707
|
const scrollTop = scrollElement.scrollTop;
|
|
4661
4708
|
const scrollHeight = scrollElement.scrollHeight;
|
|
@@ -4958,7 +5005,7 @@ var AIChatPanel = ({
|
|
|
4958
5005
|
prevResponseLengthRef.current = currentResponseLength;
|
|
4959
5006
|
const shouldAutoScroll = scrollToEndRef.current || !userHasScrolledRef.current;
|
|
4960
5007
|
if (shouldAutoScroll && response && responseGotLonger) {
|
|
4961
|
-
scrollToBottom(
|
|
5008
|
+
scrollToBottom(true);
|
|
4962
5009
|
}
|
|
4963
5010
|
}, [response, idle]);
|
|
4964
5011
|
const idleRef = (0, import_react14.useRef)(idle);
|
|
@@ -4966,21 +5013,30 @@ var AIChatPanel = ({
|
|
|
4966
5013
|
(0, import_react14.useEffect)(() => {
|
|
4967
5014
|
const scrollArea = responseAreaRef.current;
|
|
4968
5015
|
if (!scrollArea) return;
|
|
4969
|
-
const scrollViewport = scrollArea.querySelector("
|
|
5016
|
+
const scrollViewport = scrollArea.querySelector(".ai-scroll-area-viewport");
|
|
4970
5017
|
const scrollElement = scrollViewport || scrollArea;
|
|
5018
|
+
const handleWheel = (e) => {
|
|
5019
|
+
if (idleRef.current) return;
|
|
5020
|
+
if (e.deltaY < 0 && !userHasScrolledRef.current) {
|
|
5021
|
+
setUserHasScrolled(true);
|
|
5022
|
+
}
|
|
5023
|
+
};
|
|
4971
5024
|
const handleScroll = () => {
|
|
4972
|
-
if (idleRef.current || userHasScrolledRef.current) return;
|
|
4973
|
-
const currentScrollTop = scrollElement.scrollTop;
|
|
5025
|
+
if (idleRef.current || !userHasScrolledRef.current) return;
|
|
4974
5026
|
const scrollHeight = scrollElement.scrollHeight;
|
|
5027
|
+
const currentScrollTop = scrollElement.scrollTop;
|
|
4975
5028
|
const clientHeight = scrollElement.clientHeight;
|
|
4976
|
-
const isNearBottom = scrollHeight - currentScrollTop - clientHeight <
|
|
4977
|
-
if (
|
|
4978
|
-
setUserHasScrolled(
|
|
5029
|
+
const isNearBottom = scrollHeight - currentScrollTop - clientHeight < 50;
|
|
5030
|
+
if (isNearBottom) {
|
|
5031
|
+
setUserHasScrolled(false);
|
|
4979
5032
|
}
|
|
4980
|
-
lastScrollTopRef.current = currentScrollTop;
|
|
4981
5033
|
};
|
|
5034
|
+
scrollElement.addEventListener("wheel", handleWheel, { passive: true });
|
|
4982
5035
|
scrollElement.addEventListener("scroll", handleScroll, { passive: true });
|
|
4983
|
-
return () =>
|
|
5036
|
+
return () => {
|
|
5037
|
+
scrollElement.removeEventListener("wheel", handleWheel);
|
|
5038
|
+
scrollElement.removeEventListener("scroll", handleScroll);
|
|
5039
|
+
};
|
|
4984
5040
|
}, []);
|
|
4985
5041
|
(0, import_react14.useEffect)(() => {
|
|
4986
5042
|
setFollowOnQuestionsState(followOnQuestions);
|