@ash-cloud/ash-ui 0.2.2 → 0.2.4

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.cjs CHANGED
@@ -423,11 +423,17 @@ function Conversation({
423
423
  children,
424
424
  className,
425
425
  autoScroll: initialAutoScroll = true,
426
- scrollThreshold = 100
426
+ scrollThreshold = 100,
427
+ onLoadMore,
428
+ hasMore = false,
429
+ isLoadingMore = false,
430
+ loadMoreThreshold = 100
427
431
  }) {
428
432
  const containerRef = react.useRef(null);
429
433
  const [isScrolledUp, setIsScrolledUp] = react.useState(false);
430
434
  const [autoScroll, setAutoScroll] = react.useState(initialAutoScroll);
435
+ const prevScrollHeightRef = react.useRef(0);
436
+ const wasLoadingMoreRef = react.useRef(false);
431
437
  const scrollToBottom = react.useCallback((behavior = "smooth") => {
432
438
  if (containerRef.current) {
433
439
  containerRef.current.scrollTo({
@@ -445,7 +451,26 @@ function Conversation({
445
451
  if (isAtBottom && !autoScroll) {
446
452
  setAutoScroll(true);
447
453
  }
448
- }, [scrollThreshold, autoScroll]);
454
+ if (scrollTop < loadMoreThreshold && hasMore && !isLoadingMore && onLoadMore) {
455
+ onLoadMore();
456
+ }
457
+ }, [scrollThreshold, autoScroll, loadMoreThreshold, hasMore, isLoadingMore, onLoadMore]);
458
+ react.useEffect(() => {
459
+ if (isLoadingMore && !wasLoadingMoreRef.current && containerRef.current) {
460
+ prevScrollHeightRef.current = containerRef.current.scrollHeight;
461
+ }
462
+ wasLoadingMoreRef.current = isLoadingMore;
463
+ }, [isLoadingMore]);
464
+ react.useLayoutEffect(() => {
465
+ if (!isLoadingMore && prevScrollHeightRef.current > 0 && containerRef.current) {
466
+ const newScrollHeight = containerRef.current.scrollHeight;
467
+ const scrollDelta = newScrollHeight - prevScrollHeightRef.current;
468
+ if (scrollDelta > 0) {
469
+ containerRef.current.scrollTop += scrollDelta;
470
+ }
471
+ prevScrollHeightRef.current = 0;
472
+ }
473
+ }, [isLoadingMore]);
449
474
  react.useEffect(() => {
450
475
  if (autoScroll && !isScrolledUp) {
451
476
  scrollToBottom("instant");
@@ -456,7 +481,9 @@ function Conversation({
456
481
  scrollToBottom,
457
482
  isScrolledUp,
458
483
  autoScroll,
459
- setAutoScroll
484
+ setAutoScroll,
485
+ hasMore,
486
+ isLoadingMore
460
487
  };
461
488
  return /* @__PURE__ */ jsxRuntime.jsx(ConversationContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
462
489
  "div",
@@ -554,6 +581,50 @@ function ConversationScrollButton({
554
581
  }
555
582
  );
556
583
  }
584
+ function ConversationLoadMore({
585
+ className
586
+ }) {
587
+ const { hasMore, isLoadingMore } = useConversation();
588
+ if (!hasMore && !isLoadingMore) return null;
589
+ return /* @__PURE__ */ jsxRuntime.jsx(
590
+ "div",
591
+ {
592
+ className: cn(
593
+ "ash-conversation-load-more flex items-center justify-center py-3",
594
+ className
595
+ ),
596
+ children: isLoadingMore && /* @__PURE__ */ jsxRuntime.jsxs(
597
+ "svg",
598
+ {
599
+ className: "w-5 h-5 animate-spin text-[var(--ash-text-muted,rgba(255,255,255,0.5))]",
600
+ fill: "none",
601
+ viewBox: "0 0 24 24",
602
+ children: [
603
+ /* @__PURE__ */ jsxRuntime.jsx(
604
+ "circle",
605
+ {
606
+ className: "opacity-25",
607
+ cx: "12",
608
+ cy: "12",
609
+ r: "10",
610
+ stroke: "currentColor",
611
+ strokeWidth: "4"
612
+ }
613
+ ),
614
+ /* @__PURE__ */ jsxRuntime.jsx(
615
+ "path",
616
+ {
617
+ className: "opacity-75",
618
+ fill: "currentColor",
619
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
620
+ }
621
+ )
622
+ ]
623
+ }
624
+ )
625
+ }
626
+ );
627
+ }
557
628
  var ReactMarkdown = react.lazy(() => import('react-markdown'));
558
629
  function LazyMarkdown({ children, fallback, components, className }) {
559
630
  const [mounted, setMounted] = react.useState(false);
@@ -4335,6 +4406,7 @@ exports.CodeIcon = CodeIcon;
4335
4406
  exports.Conversation = Conversation;
4336
4407
  exports.ConversationContent = ConversationContent;
4337
4408
  exports.ConversationEmptyState = ConversationEmptyState;
4409
+ exports.ConversationLoadMore = ConversationLoadMore;
4338
4410
  exports.ConversationScrollButton = ConversationScrollButton;
4339
4411
  exports.CopyIcon = CopyIcon;
4340
4412
  exports.DEFAULT_STYLE_CONFIG = DEFAULT_STYLE_CONFIG;