@djangocfg/layouts 2.1.92 → 2.1.95

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "2.1.92",
3
+ "version": "2.1.95",
4
4
  "description": "Simple, straightforward layout components for Next.js - import and use with props",
5
5
  "keywords": [
6
6
  "layouts",
@@ -92,11 +92,11 @@
92
92
  "check": "tsc --noEmit"
93
93
  },
94
94
  "peerDependencies": {
95
- "@djangocfg/api": "^2.1.92",
96
- "@djangocfg/centrifugo": "^2.1.92",
97
- "@djangocfg/ui-core": "^2.1.92",
98
- "@djangocfg/ui-nextjs": "^2.1.92",
99
- "@djangocfg/ui-tools": "^2.1.92",
95
+ "@djangocfg/api": "^2.1.95",
96
+ "@djangocfg/centrifugo": "^2.1.95",
97
+ "@djangocfg/ui-core": "^2.1.95",
98
+ "@djangocfg/ui-nextjs": "^2.1.95",
99
+ "@djangocfg/ui-tools": "^2.1.95",
100
100
  "@hookform/resolvers": "^5.2.0",
101
101
  "consola": "^3.4.2",
102
102
  "lucide-react": "^0.545.0",
@@ -119,7 +119,7 @@
119
119
  "uuid": "^11.1.0"
120
120
  },
121
121
  "devDependencies": {
122
- "@djangocfg/typescript-config": "^2.1.92",
122
+ "@djangocfg/typescript-config": "^2.1.95",
123
123
  "@types/node": "^24.7.2",
124
124
  "@types/react": "^19.1.0",
125
125
  "@types/react-dom": "^19.1.0",
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import { Bot, MessageSquare, StopCircle } from 'lucide-react';
4
- import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
4
+ import React, { forwardRef, useImperativeHandle, useRef } from 'react';
5
5
 
6
- import { Button, ScrollArea, ScrollAreaHandle} from '@djangocfg/ui-nextjs';
6
+ import { Button } from '@djangocfg/ui-nextjs';
7
7
 
8
8
  import { MessageBubble } from './MessageBubble';
9
9
 
@@ -39,12 +39,10 @@ export interface ChatMessagesProps {
39
39
  /**
40
40
  * ChatMessages - Shared component for displaying chat messages
41
41
  *
42
- * Handles:
43
- * - Messages list rendering
44
- * - Greeting display when empty
45
- * - Loading indicator with stop button
46
- * - Auto-scroll on new messages
47
- * - Initial scroll on history load
42
+ * Uses flex-col-reverse for natural bottom scroll behavior:
43
+ * - Scroll position 0 = visual bottom
44
+ * - New content naturally stays at bottom
45
+ * - No complex JS scroll management needed
48
46
  */
49
47
  export const ChatMessages = forwardRef<ChatMessagesHandle, ChatMessagesProps>(
50
48
  (
@@ -60,72 +58,28 @@ export const ChatMessages = forwardRef<ChatMessagesHandle, ChatMessagesProps>(
60
58
  },
61
59
  ref
62
60
  ) => {
63
- const scrollAreaRef = useRef<ScrollAreaHandle>(null);
64
- const messagesContainerRef = useRef<HTMLDivElement>(null);
65
- const hasScrolledOnLoad = useRef(false);
61
+ const scrollContainerRef = useRef<HTMLDivElement>(null);
66
62
 
67
- // Scroll to bottom helper
68
- const scrollToBottom = useCallback((instant = false) => {
69
- if (scrollAreaRef.current) {
70
- scrollAreaRef.current.scrollToBottom(instant ? 'instant' : 'smooth');
71
- }
72
- }, []);
73
-
74
- // Scroll to last message (shows top of last message)
75
- const scrollToLastMessage = useCallback((instant = false) => {
76
- if (messagesContainerRef.current) {
77
- const messageElements = messagesContainerRef.current.querySelectorAll('[data-message-bubble]');
78
- const lastMessage = messageElements[messageElements.length - 1];
79
-
80
- if (lastMessage) {
81
- lastMessage.scrollIntoView({
82
- behavior: instant ? 'instant' : 'smooth',
83
- block: 'start',
84
- inline: 'nearest',
85
- });
86
- }
87
- }
88
- }, []);
89
-
90
- // Expose methods via ref
63
+ // Expose scroll methods via ref (for compatibility)
91
64
  useImperativeHandle(ref, () => ({
92
- scrollToBottom,
93
- scrollToLastMessage,
94
- }), [scrollToBottom, scrollToLastMessage]);
95
-
96
- // Initial scroll when history loads (instant, no animation)
97
- useEffect(() => {
98
- if (!isLoading && messages.length > 0 && !hasScrolledOnLoad.current) {
99
- // Double RAF to ensure DOM is fully updated
100
- requestAnimationFrame(() => {
101
- requestAnimationFrame(() => {
102
- // Verify messages are actually in DOM before scrolling
103
- if (messagesContainerRef.current) {
104
- const messageElements = messagesContainerRef.current.querySelectorAll('[data-message-bubble]');
105
- if (messageElements.length === messages.length) {
106
- scrollToLastMessage(true);
107
- hasScrolledOnLoad.current = true;
108
- }
109
- }
110
- });
111
- });
112
- }
113
- }, [isLoading, messages.length, scrollToLastMessage, messages]);
65
+ scrollToBottom: () => {
66
+ // With flex-col-reverse, scroll to top = visual bottom
67
+ scrollContainerRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
68
+ },
69
+ scrollToLastMessage: () => {
70
+ scrollContainerRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
71
+ },
72
+ }), []);
114
73
 
115
- // Scroll to last message on new messages (smooth animation, shows top of message)
116
- useEffect(() => {
117
- if (hasScrolledOnLoad.current && messages.length > 0) {
118
- scrollToLastMessage(false);
119
- }
120
- }, [messages, scrollToLastMessage]);
74
+ // No manual scroll effects needed - flex-col-reverse handles it naturally
121
75
 
122
76
  const GreetingIcon = greetingIcon === 'message' ? MessageSquare : Bot;
123
77
  const iconSize = largeGreetingIcon ? { container: '64px', icon: 'h-8 w-8' } : { container: '48px', icon: 'h-6 w-6' };
124
78
  const padding = largeGreetingIcon ? 'py-12' : 'py-8';
125
79
 
126
80
  return (
127
- <ScrollArea ref={scrollAreaRef} className="h-full w-full">
128
- <div ref={messagesContainerRef} className={`${isCompact ? 'p-3' : 'p-4'} space-y-4 max-w-full overflow-x-hidden`}>
81
+ <div ref={scrollContainerRef} className="h-full w-full overflow-y-auto flex flex-col-reverse">
82
+ <div className={`${isCompact ? 'p-3' : 'p-4'} space-y-4 max-w-full overflow-x-hidden`}>
129
83
  {/* Greeting */}
130
84
  {messages.length === 0 && greeting && (
131
85
  <div className={`text-center ${padding}`}>
@@ -176,7 +130,7 @@ export const ChatMessages = forwardRef<ChatMessagesHandle, ChatMessagesProps>(
176
130
  </div>
177
131
  )}
178
132
  </div>
179
- </ScrollArea>
133
+ </div>
180
134
  );
181
135
  }
182
136
  );