@@ -103,7 +103,7 @@ export const Chat = ({chatId}) => {
103
103
/>
104
104
< form className = "flex-none mb-2" onSubmit = { onSendMessage } >
105
105
< input
106
- className = "w-full rounded-lg p-2 border border-gray-500 bg-stone-800 text-stone-100"
106
+ className = "w-full rounded-lg p-2 border border-gray-500 bg-stone-800 text-stone-100 focus:outline-none "
107
107
type = "text"
108
108
name = "message"
109
109
/>
@@ -124,30 +124,22 @@ function isLastChildVisible(container) {
124
124
125
125
function SplitPane ( { messageRef, topElement, bottomElement} ) {
126
126
let [ dragging , setDragging ] = useState ( false )
127
- let [ splitPos , setSplitPos ] = useState ( 60 )
128
- let [ ghostPos , setGhostPos ] = useState ( splitPos )
127
+ let [ splitPos , setSplitPos ] = useState ( 200.5 )
129
128
let draggingRef = useRef ( )
130
- let ghostPosRef = useRef ( )
131
129
let containerRef = useRef ( )
132
130
draggingRef . current = dragging
133
- ghostPosRef . current = ghostPos
134
131
useEffect ( ( ) => {
135
132
let mousemove = ( e ) => {
136
133
if ( ! draggingRef . current ) {
137
134
return
138
135
}
139
- let pos = e . clientY
140
- let rect = containerRef . current . getBoundingClientRect ( )
141
- setGhostPos ( pos - rect . top )
136
+ setSplitPos ( getSplitPos ( e . clientY , containerRef ) )
142
137
}
143
138
let mouseup = ( e ) => {
144
139
if ( ! draggingRef . current ) {
145
140
return
146
141
}
147
- let pos = e . clientY
148
- let rect = containerRef . current . getBoundingClientRect ( )
149
- setGhostPos ( pos - rect . top )
150
- setSplitPos ( pos - rect . top )
142
+ setSplitPos ( getSplitPos ( e . clientY , containerRef ) )
151
143
setDragging ( false )
152
144
}
153
145
window . document . addEventListener ( "mousemove" , mousemove )
@@ -156,43 +148,72 @@ function SplitPane({messageRef, topElement, bottomElement}) {
156
148
window . document . removeEventListener ( "mousemove" , mousemove )
157
149
window . document . removeEventListener ( "mouseup" , mouseup )
158
150
}
159
- } , [ draggingRef , setGhostPos , setDragging ] )
151
+ } , [ draggingRef , setDragging ] )
160
152
let onMouseDown = useCallback ( ( e ) => {
161
153
e . preventDefault ( )
162
- let pos = e . clientY
163
- let rect = containerRef . current . getBoundingClientRect ( )
164
- setGhostPos ( pos - rect . top )
154
+ setSplitPos ( getSplitPos ( e . clientY , containerRef ) )
165
155
setDragging ( true )
166
- } , [ setDragging ] )
156
+ } , [ setDragging , setSplitPos ] )
157
+ let topElementHeight = Math . trunc ( splitPos )
158
+ if ( containerRef . current ) {
159
+ let rect = containerRef . current . getBoundingClientRect ( )
160
+ topElementHeight = Math . trunc ( splitPos - rect . top )
161
+ }
167
162
return (
168
163
< div
169
164
ref = { ( ref ) => {
170
165
containerRef . current = ref
171
166
} }
172
167
className = { twJoin (
173
- "grow border border-gray-500 bg-gray-900 rounded-lg flex flex-col overflow-y-hidden relative " ,
168
+ "grow border border-gray-500 bg-gray-900 rounded-lg flex flex-col overflow-y-hidden" ,
174
169
dragging && "cursor-row-resize" ,
175
170
) } >
176
171
< div
177
- style = { { height : splitPos + "px" } }
178
- className = "px-1 pt-1 flex-none overflow-y-scroll" >
172
+ style = { { height : topElementHeight + "px" } }
173
+ className = "px-1 pt-1 pb-2 flex-none overflow-y-scroll" >
179
174
{ topElement }
180
175
</ div >
181
- < div
182
- onMouseDown = { onMouseDown }
183
- className = { twJoin (
184
- "w-full flex-none h-[3px] cursor-row-resize" ,
185
- ! dragging && "bg-gray-500" ,
186
- dragging && "bg-transparent" ,
187
- ) } />
188
- { dragging && (
189
- < div
190
- style = { { top : ghostPos + "px" } }
191
- className = "w-full absolute h-[3px] bg-gray-500 z-20" />
192
- ) }
193
- < div ref = { messageRef } className = "px-1 overflow-y-scroll" >
176
+ < SplitBar
177
+ containerRef = { containerRef }
178
+ splitPos = { splitPos }
179
+ dragging = { dragging }
180
+ onMouseDown = { onMouseDown } />
181
+ < div ref = { messageRef } className = "px-1 pt-3 pb-1 overflow-y-scroll" >
194
182
{ bottomElement }
195
183
</ div >
196
184
</ div >
197
185
)
198
186
}
187
+
188
+ function SplitBar ( { splitPos, dragging, onMouseDown, containerRef} ) {
189
+ let width = 100 , left = 10 // some default values
190
+ if ( containerRef . current ) {
191
+ let container = containerRef . current
192
+ let rect = containerRef . current . getBoundingClientRect ( )
193
+ let parentRect = container . parentNode . getBoundingClientRect ( )
194
+ width = rect . width
195
+ left = rect . left - parentRect . left
196
+ }
197
+ return < >
198
+ < div
199
+ onMouseDown = { dragging ? undefined : onMouseDown }
200
+ style = { { top : Math . trunc ( splitPos - 1 ) + 0.5 , width : width , left : left } }
201
+ className = "absolute h-[1px] bg-gray-500 z-20 cursor-row-resize" />
202
+ < div
203
+ onMouseDown = { dragging ? undefined : onMouseDown }
204
+ style = { { top : Math . trunc ( splitPos ) + 0.5 , width : width , left : left } }
205
+ className = "absolute h-[5px] bg-slate-800 z-20 cursor-row-resize" />
206
+ < div
207
+ onMouseDown = { dragging ? undefined : onMouseDown }
208
+ style = { { top : Math . trunc ( splitPos + 5 ) + 0.5 , width : width , left : left } }
209
+ className = "absolute h-[1px] bg-gray-500 z-20 cursor-row-resize" />
210
+ </ >
211
+ }
212
+
213
+ function getSplitPos ( clientY , containerRef ) {
214
+ let rect = containerRef . current . getBoundingClientRect ( )
215
+ let result = clientY
216
+ result = Math . max ( rect . top + 40 , result )
217
+ result = Math . min ( rect . top + rect . height - 40 , result )
218
+ return Math . trunc ( result )
219
+ }
0 commit comments