@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 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" }, icon, /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__title" }, displayTitle), isStreaming && /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__streaming-indicator" }, /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__streaming-dot" }), /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__streaming-dot" }), /* @__PURE__ */ import_react10.default.createElement("span", { className: "thinking-block__streaming-dot" }))),
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 (scrollToEnd) {
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.scrollTo({
2183
- top: responseArea.scrollHeight,
2184
- behavior: "smooth"
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: "smooth", block: "end" });
2210
+ (_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "auto", block: "end" });
2188
2211
  }
2189
- } else {
2190
- const responseArea = responseAreaRef.current;
2191
- if (responseArea) {
2192
- setHasScroll(hasVerticalScrollbar(responseArea));
2193
- const handleScroll = () => {
2194
- const isScrolledToBottom = responseArea.scrollHeight - responseArea.scrollTop === responseArea.clientHeight;
2195
- setIsAtBottom(isScrolledToBottom);
2196
- };
2197
- handleScroll();
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
- }, [response, history]);
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("[data-radix-scroll-area-viewport]");
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(false);
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("[data-radix-scroll-area-viewport]");
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 < 100;
4977
- if (currentScrollTop < lastScrollTopRef.current && !isNearBottom) {
4978
- setUserHasScrolled(true);
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 () => scrollElement.removeEventListener("scroll", handleScroll);
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);