/* Copyright 2023, 2024 New Vector Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ import { type ComponentType, type JSX, memo, type RefObject, useRef, } from "react"; import { type EventTypes, type Handler, useDrag } from "@use-gesture/react"; import { type SpringValue } from "@react-spring/web"; import classNames from "classnames"; import { type TileProps } from "./Grid"; import styles from "./TileWrapper.module.css"; interface Props { id: string; onDrag: RefObject< ( tileId: string, state: Parameters>[0], ) => void > | null; /** * The width this tile will have once its animations have settled. */ targetWidth: number; /** * The width this tile will have once its animations have settled. */ targetHeight: number; model: M; Tile: ComponentType>; opacity: SpringValue; scale: SpringValue; zIndex: SpringValue; x: SpringValue; y: SpringValue; width: SpringValue; height: SpringValue; } const TileWrapper_ = memo( ({ id, onDrag, targetWidth, targetHeight, model, Tile, opacity, scale, zIndex, x, y, width, height, }: Props) => { const ref = useRef(null); useDrag((state) => onDrag?.current!(id, state), { target: ref, filterTaps: true, // Previous designs, which allowed tiles to be dragged and dropped around // the scrolling grid, required us to set preventScroll to true here. But // our designs no longer call for this, and meanwhile there's a bug in // use-gesture that causes filterTaps + preventScroll to break buttons // within tiles (like the 'switch camera' button) on mobile. // https://github.com/pmndrs/use-gesture/issues/593 }); return ( ); }, ); TileWrapper_.displayName = "TileWrapper"; /** * A wrapper around a tile in a video grid. This component exists to decouple * child components from the grid. */ // We pretend this component is a simple function rather than a // NamedExoticComponent, because that's the only way we can fit in a type // parameter export const TileWrapper = TileWrapper_ as ( props: Props, ) => JSX.Element;