@@ -2,73 +2,90 @@ import * as React from "react";
22import { cn } from "@/lib/utils" ;
33
44type PopoverContextType = {
5- open : boolean ;
6- setOpen : ( open : boolean ) => void ;
5+ open : boolean ;
6+ setOpen : ( open : boolean ) => void ;
77} ;
88
9- const PopoverContext = React . createContext < PopoverContextType | undefined > ( undefined ) ;
9+ const PopoverContext = React . createContext < PopoverContextType | undefined > (
10+ undefined ,
11+ ) ;
1012
1113type PopoverProps = React . ComponentProps < "div" > & {
12- open ?: boolean ;
13- onOpenChange ?: ( open : boolean ) => void ;
14+ open ?: boolean ;
15+ onOpenChange ?: ( open : boolean ) => void ;
1416} ;
1517
16- export function Popover ( { className, open, onOpenChange, children, ...props } : PopoverProps ) {
17- const [ isOpen , setIsOpen ] = React . useState ( open ?? false ) ;
18- React . useEffect ( ( ) => {
19- if ( typeof open === "boolean" ) setIsOpen ( open ) ;
20- } , [ open ] ) ;
21- const handleOpenChange = ( next : boolean ) => {
22- setIsOpen ( next ) ;
23- onOpenChange ?.( next ) ;
24- } ;
25- return (
26- < PopoverContext . Provider value = { { open : isOpen , setOpen : handleOpenChange } } >
27- < div className = { cn ( "relative" , className ) } { ...props } >
28- { children }
29- </ div >
30- </ PopoverContext . Provider >
31- ) ;
18+ export function Popover ( {
19+ className,
20+ open,
21+ onOpenChange,
22+ children,
23+ ...props
24+ } : PopoverProps ) {
25+ const [ isOpen , setIsOpen ] = React . useState ( open ?? false ) ;
26+ React . useEffect ( ( ) => {
27+ if ( typeof open === "boolean" ) setIsOpen ( open ) ;
28+ } , [ open ] ) ;
29+ const handleOpenChange = ( next : boolean ) => {
30+ setIsOpen ( next ) ;
31+ onOpenChange ?.( next ) ;
32+ } ;
33+ return (
34+ < PopoverContext . Provider
35+ value = { { open : isOpen , setOpen : handleOpenChange } }
36+ >
37+ < div className = { cn ( "relative" , className ) } { ...props } >
38+ { children }
39+ </ div >
40+ </ PopoverContext . Provider >
41+ ) ;
3242}
3343
34- export function PopoverTrigger ( { asChild, ...props } : { asChild ?: boolean } & React . ComponentProps < "button" > ) {
35- const context = React . useContext ( PopoverContext ) ;
36- if ( ! context ) throw new Error ( "PopoverTrigger must be used within a Popover" ) ;
37- const { open, setOpen } = context ;
38- if ( asChild && React . isValidElement ( props . children ) ) {
39- // Inject onClick to child
40- return React . cloneElement ( props . children as React . ReactElement , {
41- onClick : ( e : React . MouseEvent ) => {
42- props . children . props . onClick ?.( e ) ;
43- setOpen ( ! open ) ;
44- } ,
45- 'aria-expanded' : open ,
46- } ) ;
47- }
48- return (
49- < button
50- { ...props }
51- onClick = { ( e ) => {
52- props . onClick ?.( e ) ;
53- setOpen ( ! open ) ;
54- } }
55- aria-expanded = { open }
56- />
57- ) ;
44+ export function PopoverTrigger ( {
45+ asChild,
46+ ...props
47+ } : { asChild ?: boolean } & React . ComponentProps < "button" > ) {
48+ const context = React . useContext ( PopoverContext ) ;
49+ if ( ! context ) throw new Error ( "PopoverTrigger must be used within a Popover" ) ;
50+ const { open, setOpen } = context ;
51+ if ( asChild && React . isValidElement ( props . children ) ) {
52+ // Inject onClick to child
53+ const childProps = ( props . children as React . ReactElement < any > ) . props ;
54+ return React . cloneElement ( props . children as React . ReactElement < any > , {
55+ onClick : ( e : React . MouseEvent ) => {
56+ childProps ?. onClick ?.( e ) ;
57+ setOpen ( ! open ) ;
58+ } ,
59+ "aria-expanded" : open ,
60+ } ) ;
61+ }
62+ return (
63+ < button
64+ { ...props }
65+ onClick = { ( e ) => {
66+ props . onClick ?.( e ) ;
67+ setOpen ( ! open ) ;
68+ } }
69+ aria-expanded = { open }
70+ />
71+ ) ;
5872}
5973
60- export function PopoverContent ( { className, ...props } : React . ComponentProps < "div" > ) {
61- const context = React . useContext ( PopoverContext ) ;
62- if ( ! context ) throw new Error ( "PopoverContent must be used within a Popover" ) ;
63- const { open } = context ;
64- if ( ! open ) return null ;
65- return (
66- < div
67- className = { cn (
68- "absolute z-50 mt-2 w-auto min-w-[8rem] max-w-[90vw] rounded-md border bg-white p-2 text-black shadow-md outline-none" ,
69- className
70- ) }
71- { ...props }
72- />
73- ) ;
74+ export function PopoverContent ( {
75+ className,
76+ ...props
77+ } : React . ComponentProps < "div" > ) {
78+ const context = React . useContext ( PopoverContext ) ;
79+ if ( ! context ) throw new Error ( "PopoverContent must be used within a Popover" ) ;
80+ const { open } = context ;
81+ if ( ! open ) return null ;
82+ return (
83+ < div
84+ className = { cn (
85+ "absolute z-50 mt-2 w-auto min-w-[8rem] max-w-[90vw] rounded-md border bg-white p-2 text-black shadow-md outline-none" ,
86+ className ,
87+ ) }
88+ { ...props }
89+ />
90+ ) ;
7491}
0 commit comments