@@ -46,6 +46,7 @@ const CHAT_MESSAGE_TAG = "shiny-chat-message";
4646const  CHAT_USER_MESSAGE_TAG  =  "shiny-user-message" ; 
4747const  CHAT_MESSAGES_TAG  =  "shiny-chat-messages" ; 
4848const  CHAT_INPUT_TAG  =  "shiny-chat-input" ; 
49+ const  CHAT_INPUT_SENTINEL_TAG  =  "shiny-chat-input-sentinel" ; 
4950const  CHAT_CONTAINER_TAG  =  "shiny-chat-container" ; 
5051
5152const  ICONS  =  { 
@@ -262,6 +263,8 @@ class ChatInput extends LightElement {
262263} 
263264
264265class  ChatContainer  extends  LightElement  { 
266+   inputSentinel ?: HTMLElement ; 
267+   inputSentinelObserver ?: IntersectionObserver ; 
265268
266269  private  get  input ( ) : ChatInput  { 
267270    return  this . querySelector ( CHAT_INPUT_TAG )  as  ChatInput ; 
@@ -280,6 +283,34 @@ class ChatContainer extends LightElement {
280283    return  html `` ; 
281284  } 
282285
286+   connectedCallback ( ) : void { 
287+     super . connectedCallback ( ) ; 
288+ 
289+     // We use a sentinel element that we place just above the shiny-chat-input. When it 
290+     // moves off-screen we know that the text area input is now floating, add shadow. 
291+     let  sentinel  =  this . querySelector < HTMLElement > ( CHAT_INPUT_SENTINEL_TAG ) ; 
292+     if  ( ! sentinel )  { 
293+       sentinel  =  createElement ( CHAT_INPUT_SENTINEL_TAG ,  { } )  as  HTMLElement ; 
294+       this . input . insertAdjacentElement ( "beforebegin" ,  sentinel ) ; 
295+     } 
296+ 
297+     this . inputSentinel  =  sentinel ; 
298+     this . inputSentinelObserver  =  new  IntersectionObserver ( 
299+       ( entries )  =>  { 
300+         const  inputTextarea  =  this . input . querySelector ( "textarea" ) ; 
301+         if  ( ! inputTextarea )  return ; 
302+         const  addShadow  =  entries [ 0 ] ?. intersectionRatio  ===  0 ; 
303+         inputTextarea . classList . toggle ( "shadow" ,  addShadow ) ; 
304+       } , 
305+       { 
306+         threshold : [ 0 ,  1 ] , 
307+         rootMargin : "0px" , 
308+       } 
309+     ) ; 
310+ 
311+     this . inputSentinelObserver . observe ( this . inputSentinel ) ; 
312+   } 
313+ 
283314  firstUpdated ( ) : void { 
284315    // Don't attach event listeners until child elements are rendered 
285316    if  ( ! this . messages )  return ; 
@@ -306,6 +337,9 @@ class ChatContainer extends LightElement {
306337  disconnectedCallback ( ) : void { 
307338    super . disconnectedCallback ( ) ; 
308339
340+     this . inputSentinelObserver ?. disconnect ( ) ; 
341+     this . inputSentinel ?. remove ( ) ; 
342+ 
309343    this . removeEventListener ( "shiny-chat-input-sent" ,  this . #onInputSent) ; 
310344    this . removeEventListener ( "shiny-chat-append-message" ,  this . #onAppend) ; 
311345    this . removeEventListener ( 
0 commit comments