mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-06 08:57:46 +00:00
38c131e02c
The core component of the PiP layout. Adapted from a simplified version of @ovgodd's work in #890 — see that PR for context on the original design. Co-authored-by: Cyril <c.gromoff@gmail.com>
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { memo, useMemo, useRef } from 'react'
|
|
import type { TrackReferenceOrPlaceholder } from '@livekit/components-core'
|
|
import { styled } from '@/styled-system/jsx'
|
|
import { ParticipantTile } from '@/features/rooms/livekit/components/ParticipantTile'
|
|
import { usePipElementSize } from '../../hooks/usePipElementSize'
|
|
import { computePipGridLayout } from '../../utils/pipGrid'
|
|
import { getTrackKey } from '../../utils/pipTrackSelection'
|
|
|
|
type PipGridLayoutProps = {
|
|
tracks: TrackReferenceOrPlaceholder[]
|
|
}
|
|
|
|
/**
|
|
* Adaptive grid used when 3+ tracks are visible in the PiP window.
|
|
*
|
|
* All grid math (shape choice + partial-row stretching) is delegated to
|
|
* `computePipGridLayout`. This component only measures the container,
|
|
* applies the returned placements, and plays a FLIP animation when the
|
|
* tile set or grid shape changes (participant joins/leaves or shape shift).
|
|
*
|
|
* Tiles keep a stable key so resizing never remounts <video> elements.
|
|
*/
|
|
export const PipGridLayout = memo(({ tracks }: PipGridLayoutProps) => {
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
const { width, height } = usePipElementSize(containerRef)
|
|
|
|
const { rows, subColumns, placements } = useMemo(
|
|
() => computePipGridLayout(tracks.length, width, height),
|
|
[tracks.length, width, height]
|
|
)
|
|
|
|
const gridStyle = useMemo(
|
|
() => ({
|
|
gridTemplateColumns: `repeat(${subColumns}, minmax(0, 1fr))`,
|
|
gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`,
|
|
}),
|
|
[subColumns, rows]
|
|
)
|
|
|
|
return (
|
|
<GridContainer ref={containerRef} style={gridStyle}>
|
|
{tracks.map((track, index) => (
|
|
<GridCell key={getTrackKey(track)} style={placements[index]}>
|
|
<ParticipantTile trackRef={track} />
|
|
</GridCell>
|
|
))}
|
|
</GridContainer>
|
|
)
|
|
})
|
|
PipGridLayout.displayName = 'PipGridLayout'
|
|
|
|
const GridContainer = styled('div', {
|
|
base: {
|
|
width: '100%',
|
|
height: '100%',
|
|
display: 'grid',
|
|
gap: '0.25rem',
|
|
},
|
|
})
|
|
|
|
const GridCell = styled('div', {
|
|
base: {
|
|
position: 'relative',
|
|
minWidth: 0,
|
|
minHeight: 0,
|
|
borderRadius: '4px',
|
|
overflow: 'hidden',
|
|
backgroundColor: 'primaryDark.100',
|
|
// Paint on own layer so FLIP transforms don't trigger layout thrash.
|
|
willChange: 'transform',
|
|
'& .lk-participant-tile': {
|
|
width: '100%',
|
|
height: '100%',
|
|
},
|
|
},
|
|
})
|