- MediaViewer branches by type: pdf (native iframe), text/json (viewer +
copy), html (sandboxed allow-scripts run + source toggle), image (zoom/
pan/rotate lightbox + Edit), video (brand player + Trim)
- ImageEditor: canvas crop (drag + aspect presets), rotate 90s, flip H/V,
brightness/contrast/saturation; Save as copy uploads a NEW library file
via the direct path (server fallback)
- VideoTrim: in/out over the duration; Cut in Video Studio registers the
same R2 object as a video_asset, creates a one-clip EDL at the trim, and
queues the assemble render — the cut lands in the Video library, the
original file is never modified
- invalid type syntax fixed across the new components (prop callbacks use
arrow types)