@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.
|
|
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.
|
|
96
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
97
|
-
"@djangocfg/ui-core": "^2.1.
|
|
98
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
99
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
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.
|
|
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,
|
|
4
|
+
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
|
|
5
5
|
|
|
6
|
-
import { Button
|
|
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
|
-
*
|
|
43
|
-
* -
|
|
44
|
-
* -
|
|
45
|
-
* -
|
|
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
|
|
64
|
-
const messagesContainerRef = useRef<HTMLDivElement>(null);
|
|
65
|
-
const hasScrolledOnLoad = useRef(false);
|
|
61
|
+
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
|
66
62
|
|
|
67
|
-
//
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
//
|
|
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
|
-
<
|
|
128
|
-
<div
|
|
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
|
-
</
|
|
133
|
+
</div>
|
|
180
134
|
);
|
|
181
135
|
}
|
|
182
136
|
);
|