1- import { useMemo } from 'react' ;
1+ import { type ReactNode , useMemo } from 'react' ;
22import { type VariantProps , cva } from 'class-variance-authority' ;
33import { type LocalAudioTrack , type RemoteAudioTrack } from 'livekit-client' ;
44import {
55 type AgentState ,
66 type TrackReferenceOrPlaceholder ,
77 useMultibandTrackVolume ,
88} from '@livekit/components-react' ;
9- import { cn } from '@/lib/utils' ;
9+ import { cloneSingleChild , cn } from '@/lib/utils' ;
1010import { useBarAnimator } from './hooks/useBarAnimator' ;
1111
12- export const audioBarVisualizerVariants = cva ( [ 'relative flex items-center justify-center' ] , {
13- variants : {
14- size : {
15- icon : 'h-[24px] gap-[2px]' ,
16- sm : 'h-[56px] gap-[4px]' ,
17- md : 'h-[112px] gap-[8px]' ,
18- lg : 'h-[224px] gap-[16px]' ,
19- xl : 'h-[448px] gap-[32px]' ,
20- } ,
21- } ,
22- defaultVariants : {
23- size : 'md' ,
24- } ,
25- } ) ;
26-
27- export const audioBarVisualizerBarVariants = cva (
12+ export const audioBarVisualizerVariants = cva (
2813 [
29- 'rounded-full transition-colors duration-250 ease-linear bg-(--audio-visualizer-idle) data-[lk-highlighted=true]:bg-(--audio-visualizer-active)' ,
14+ 'relative flex items-center justify-center' ,
15+ '[&_>_*]:rounded-full [&_>_*]:transition-colors [&_>_*]:duration-250 [&_>_*]:ease-linear' ,
16+ '[&_>_*]:bg-(--audio-visualizer-idle) [&_>_*]:data-[lk-highlighted=true]:bg-(--audio-visualizer-active)' ,
3017 ] ,
3118 {
3219 variants : {
3320 size : {
34- icon : ' w-[4px] min-h-[4px]',
35- sm : ' w-[8px] min-h-[8px]',
36- md : ' w-[16px] min-h-[16px]',
37- lg : ' w-[32px] min-h-[32px]',
38- xl : ' w-[64px] min-h-[64px]',
21+ icon : [ 'h-[24px] gap-[2px]' , '[&_>_*]: w-[4px] [&_>_*]: min-h-[4px]'] ,
22+ sm : [ 'h-[56px] gap-[4px]' , '[&_>_*]: w-[8px] [&_>_*]: min-h-[8px]'] ,
23+ md : [ 'h-[112px] gap-[8px]' , '[&_>_*]: w-[16px] [&_>_*]: min-h-[16px]'] ,
24+ lg : [ 'h-[224px] gap-[16px]' , '[&_>_*]: w-[32px] [&_>_*]: min-h-[32px]'] ,
25+ xl : [ 'h-[448px] gap-[32px]' , '[&_>_*]: w-[64px] [&_>_*]: min-h-[64px]'] ,
3926 } ,
4027 } ,
4128 defaultVariants : {
@@ -49,7 +36,7 @@ interface AudioBarVisualizerProps {
4936 barCount ?: number ;
5037 audioTrack ?: LocalAudioTrack | RemoteAudioTrack | TrackReferenceOrPlaceholder ;
5138 className ?: string ;
52- barClassName ?: string ;
39+ children ?: ReactNode | ReactNode [ ] ;
5340}
5441
5542export function AudioBarVisualizer ( {
@@ -58,7 +45,7 @@ export function AudioBarVisualizer({
5845 barCount,
5946 audioTrack,
6047 className,
61- barClassName ,
48+ children ,
6249} : AudioBarVisualizerProps & VariantProps < typeof audioBarVisualizerVariants > ) {
6350 const _barCount = useMemo ( ( ) => {
6451 if ( barCount ) {
@@ -95,19 +82,27 @@ export function AudioBarVisualizer({
9582 } , [ state , _barCount ] ) ;
9683
9784 const highlightedIndices = useBarAnimator ( state , _barCount , sequencerInterval ) ;
98-
9985 const bands = audioTrack ? volumeBands : new Array ( _barCount ) . fill ( 0 ) ;
86+
10087 return (
10188 < div className = { cn ( audioBarVisualizerVariants ( { size } ) , className ) } >
102- { bands . map ( ( band , idx ) => (
103- < div
104- key = { idx }
105- data-lk-index = { idx }
106- data-lk-highlighted = { highlightedIndices . includes ( idx ) }
107- className = { cn ( audioBarVisualizerBarVariants ( { size } ) , barClassName ) }
108- style = { { height : `${ band * 100 } %` } }
109- />
110- ) ) }
89+ { bands . map ( ( band , idx ) =>
90+ children ? (
91+ cloneSingleChild ( children , {
92+ key : idx ,
93+ 'data-lk-index' : idx ,
94+ 'data-lk-highlighted' : highlightedIndices . includes ( idx ) ,
95+ style : { height : `${ band * 100 } %` } ,
96+ } )
97+ ) : (
98+ < div
99+ key = { idx }
100+ data-lk-index = { idx }
101+ data-lk-highlighted = { highlightedIndices . includes ( idx ) }
102+ style = { { height : `${ band * 100 } %` } }
103+ />
104+ )
105+ ) }
111106 </ div >
112107 ) ;
113108}
0 commit comments