@@ -32,6 +32,8 @@ export function BeatCanvasComposerShell({
3232 isPromptComposing,
3333 labels,
3434 onActiveComposerCardIdChange,
35+ onComposerFocusChange,
36+ onComposerPointerChange,
3537 onPromptChange,
3638 onPromptCommit,
3739 onGenerateDraft,
@@ -54,6 +56,8 @@ export function BeatCanvasComposerShell({
5456 isPromptComposing : boolean ;
5557 labels : CanvasLabels ;
5658 onActiveComposerCardIdChange : ( cardId : string | null ) => void ;
59+ onComposerFocusChange ?: ( isFocusWithinComposer : boolean ) => void ;
60+ onComposerPointerChange ?: ( isPointerWithinComposer : boolean ) => void ;
5761 onPromptChange : ( nextPrompt : string ) => void ;
5862 onPromptCommit : ( nextPrompt : string ) => void ;
5963 onGenerateDraft : ( draftId : string ) => void ;
@@ -121,14 +125,27 @@ export function BeatCanvasComposerShell({
121125 < section
122126 ref = { composerRef }
123127 className = { cn (
124- 'beat-composer pointer-events-auto absolute z-[60] isolate' ,
128+ 'beat-composer beat-pop-in pointer-events-auto absolute z-[60] isolate' ,
125129 composerCardClassName ,
126130 'w-[min(560px,calc(100vw-32px))]' ,
127131 position ? '' : 'bottom-[98px] left-1/2 -translate-x-1/2'
128132 ) }
129133 style = { position ? { left : position . left , top : position . top } : undefined }
130134 onPointerDown = { stopComposerEvent }
131135 onPointerDownCapture = { stopComposerEvent }
136+ onPointerEnter = { ( ) => onComposerPointerChange ?.( true ) }
137+ onPointerLeave = { ( ) => onComposerPointerChange ?.( false ) }
138+ onFocusCapture = { ( ) => onComposerFocusChange ?.( true ) }
139+ onBlurCapture = { ( event ) => {
140+ const nextFocusedElement = event . relatedTarget ;
141+ if (
142+ nextFocusedElement instanceof Node &&
143+ event . currentTarget . contains ( nextFocusedElement )
144+ ) {
145+ return ;
146+ }
147+ onComposerFocusChange ?.( false ) ;
148+ } }
132149 onKeyDownCapture = { stopComposerKeyboardEvent }
133150 onKeyUpCapture = { stopComposerKeyboardEvent }
134151 >
0 commit comments