import type { Meta, StoryFn } from '@storybook/react' import React from 'react' import { StoryGrid, StoryHeading, StoryPage, StoryRow, } from '../stories/StoryTable' import type { VideoItem } from '../types' import VideoAttachment from '.' // Sourced from `.storybook/public/` so we share the same assets used by // the LockedAttachment stories. const VIDEO_SRC = '/video-source.mp4' const VIDEO_POSTER = '/video-thumbnail.jpg' const STACK_VIDEOS: VideoItem[] = [ { src: VIDEO_SRC, poster: VIDEO_POSTER, mimeType: 'video/mp4', }, { src: VIDEO_SRC, poster: VIDEO_POSTER, mimeType: 'video/mp4', }, { src: VIDEO_SRC, poster: VIDEO_POSTER, mimeType: 'video/mp4', }, { src: VIDEO_SRC, poster: VIDEO_POSTER, mimeType: 'video/mp4', }, ] /** * Nine clips — four tiles plus a `+5` scrim on the bottom-right. The cap * on the creator surface is 10 attachments, so the reachable badge range * is `+1` … `+6`; this is real production state, not defensive UI. */ const OVERFLOW_VIDEOS: VideoItem[] = Array.from({ length: 9 }, () => ({ src: VIDEO_SRC, poster: VIDEO_POSTER, mimeType: 'video/mp4', })) /** * Solid-colour poster at an exact intrinsic size. The single-video card * measures `naturalWidth / naturalHeight` off the decoded poster, so the * aspect row needs posters whose ratio is declared rather than inherited * from whatever photo happens to sit in `.storybook/public/`. */ const aspectPoster = (width: number, height: number): string => `data:image/svg+xml;utf8,${encodeURIComponent( `` )}` const meta: Meta = { title: 'MessageAttachment/Video', parameters: { layout: 'fullscreen' }, } export default meta const handleDismiss = () => { console.log('Dismissed video attachment') } /** * Single video — the bubble shows the poster with a play overlay. * Clicking opens the full-viewport `VideoViewer` with native controls * (play / pause / seek / fullscreen / volume / download). */ export const Single: StoryFn = () => ( } sent={ } received={ } /> } sent={ } received={ } /> ) /** Single video with an accompanying caption. Sent + Received only — * composer captions live in the message input, not the attachment * preview. */ export const SingleWithText: StoryFn = () => ( } sent={ } received={ } /> ) /** Stacked video attachments. Sent + Received only — the composer * surface accepts a single video at a time. */ export const Stacked: StoryFn = () => ( } sent={ } received={ } /> } sent={ } received={ } /> } sent={} received={ } /> ) /** Stacked videos with an accompanying caption. * Sent + Received only — see `Stacked` for the rationale. */ export const StackedWithText: StoryFn = () => ( } sent={ } received={ } /> ) /** Stacked videos past the 4-tile grid — the last visible tile trades * its play badge for the `+N` count scrim. */ export const Overflow: StoryFn = () => ( } received={ } /> } received={ } /> } received={ } /> ) /** Single-video cards size themselves to the poster's own aspect, clamped * to `[4/5, 16/9]` so one portrait clip can't dominate the thread. */ export const SingleAspect: StoryFn = () => ( } received={ } /> } received={ } /> } received={ } /> } received={ } /> )