11"use client" ;
22
33import { Check , ChevronDown , Plus , Reply , X } from "lucide-react" ;
4- import { useEffect , useId , useLayoutEffect , useRef , useState } from "react" ;
4+ import {
5+ forwardRef ,
6+ useEffect ,
7+ useId ,
8+ useLayoutEffect ,
9+ useRef ,
10+ useState ,
11+ } from "react" ;
512import type * as React from "react" ;
613
714import { useControllableState } from "../hooks/use-controllable-state.js" ;
@@ -234,18 +241,23 @@ export type PromptInputAddMenuProps = Omit<
234241 * elsewhere in the enclosing `PromptInput` (the textarea, beside a menu the
235242 * host opened).
236243 */
237- export function PromptInputAddMenu ( {
238- items,
239- disabled : disabledProp ,
240- label = "Add" ,
241- align = "start" ,
242- open : openProp ,
243- defaultOpen = false ,
244- onOpenChange,
245- className,
244+ export const PromptInputAddMenu = forwardRef <
245+ HTMLDivElement ,
246+ PromptInputAddMenuProps
247+ > ( function PromptInputAddMenu (
248+ {
249+ items,
250+ disabled : disabledProp ,
251+ label = "Add" ,
252+ align = "start" ,
253+ open : openProp ,
254+ defaultOpen = false ,
255+ onOpenChange,
256+ className,
257+ ...props
258+ } ,
246259 ref ,
247- ...props
248- } : PromptInputAddMenuProps ) {
260+ ) {
249261 const popover = useDismissablePopover < HTMLDivElement , HTMLButtonElement > ( {
250262 open : openProp ,
251263 defaultOpen,
@@ -406,7 +418,7 @@ export function PromptInputAddMenu({
406418 ) : null }
407419 </ div >
408420 ) ;
409- }
421+ } ) ;
410422
411423/** An option as the shared select draws it. */
412424type SelectOption = {
@@ -474,22 +486,24 @@ type OptionSelectProps = SelectStateProps & {
474486 * `PromptInput` (the textarea, beside a list the host opened) closes it too
475487 * and leaves focus where it is.
476488 */
477- function OptionSelect ( {
478- slot,
479- label,
480- options,
481- value : valueProp ,
482- defaultValue,
483- onValueChange,
484- open : openProp ,
485- defaultOpen = false ,
486- onOpenChange,
487- disabled : disabledProp ,
488- align = "start" ,
489- className,
490- ref,
491- ...props
492- } : OptionSelectProps ) {
489+ const OptionSelect = forwardRef ( function OptionSelect (
490+ {
491+ slot,
492+ label,
493+ options,
494+ value : valueProp ,
495+ defaultValue,
496+ onValueChange,
497+ open : openProp ,
498+ defaultOpen = false ,
499+ onOpenChange,
500+ disabled : disabledProp ,
501+ align = "start" ,
502+ className,
503+ ...props
504+ } : Omit < OptionSelectProps , "ref" > ,
505+ ref : React . ForwardedRef < HTMLDivElement > ,
506+ ) {
493507 // Undefined until something is chosen: the first option then stands in,
494508 // read from the current list so options that load late still get it.
495509 const [ picked , setPicked ] = useControllableState < string | undefined > ( {
@@ -702,7 +716,7 @@ function OptionSelect({
702716 ) : null }
703717 </ div >
704718 ) ;
705- }
719+ } ) ;
706720
707721/** A model to choose from in `PromptInputModelSelect`. */
708722export type PromptInputModelOption = {
@@ -728,15 +742,17 @@ export type PromptInputModelSelectProps = SelectStateProps & {
728742 * reasoning level, is a separate control, so `onValueChange` stays a single
729743 * model id.
730744 */
731- export function PromptInputModelSelect ( {
732- models,
733- label = "Model" ,
734- align = "end" ,
735- ...props
736- } : PromptInputModelSelectProps ) {
745+ export const PromptInputModelSelect = forwardRef <
746+ HTMLDivElement ,
747+ PromptInputModelSelectProps
748+ > ( function PromptInputModelSelect (
749+ { models, label = "Model" , align = "end" , ...props } ,
750+ ref ,
751+ ) {
737752 return (
738753 < OptionSelect
739754 { ...props }
755+ ref = { ref }
740756 slot = "prompt-input-model-select"
741757 label = { label }
742758 align = { align }
@@ -749,7 +765,7 @@ export function PromptInputModelSelect({
749765 } ) ) }
750766 />
751767 ) ;
752- }
768+ } ) ;
753769
754770/** A way of working, offered by `PromptInputModeSelect`. */
755771export type PromptInputModeOption = {
@@ -766,14 +782,14 @@ export type PromptInputModeSelectProps = SelectStateProps & {
766782
767783/** How the agent works this turn. The modes' labels and details are the
768784 * host's own strings; the trigger shows the chosen mode's label. */
769- export function PromptInputModeSelect ( {
770- modes,
771- label = "Mode" ,
772- ...props
773- } : PromptInputModeSelectProps ) {
785+ export const PromptInputModeSelect = forwardRef <
786+ HTMLDivElement ,
787+ PromptInputModeSelectProps
788+ > ( function PromptInputModeSelect ( { modes, label = "Mode" , ...props } , ref ) {
774789 return (
775790 < OptionSelect
776791 { ...props }
792+ ref = { ref }
777793 slot = "prompt-input-mode-select"
778794 label = { label }
779795 options = { modes . map ( ( mode ) => ( {
@@ -784,7 +800,7 @@ export function PromptInputModeSelect({
784800 } ) ) }
785801 />
786802 ) ;
787- }
803+ } ) ;
788804
789805export type PromptInputFloatProps = React . ComponentProps < "div" > ;
790806
0 commit comments