feat(studio): always-on crop with reposition handle, drop crop mode (#2090)

Crop is now part of the element selection instead of a separate mode. Selecting
a croppable element shows edge handles just outside each side and, once cropped,
the full content with the cropped-away area dimmed plus a center reposition
handle to pan the crop window. Dragging the body moves the element, edge handles
crop, the center handle pans; corners stay free for the resize handle. Removes
the crop-mode toggle (toolbar + property-panel buttons), the cropMode/
cropAvailable player-store state, and the double-click-to-crop gesture. The
clip-path inset model is unchanged.
This commit is contained in:
Miguel Ángel
2026-07-08 22:24:26 -04:00
committed by GitHub
parent 6f0b57d608
commit 623f91d6a1
15 changed files with 217 additions and 307 deletions
@@ -63,10 +63,8 @@ const SHORTCUT_SECTIONS = [
{
title: "Crop",
hints: [
{ key: "DblClick", label: "Crop selected element" },
{ key: "Drag edge", label: "Adjust crop side" },
{ key: "Drag frame", label: "Move crop window" },
{ key: "Esc", label: "Exit crop (or click outside)" },
{ key: "Drag edge", label: "Crop a side" },
{ key: "Drag center", label: "Reposition the crop" },
],
},
{
@@ -113,15 +113,6 @@ interface PlayerState {
autoKeyframeEnabled: boolean;
setAutoKeyframeEnabled: (enabled: boolean) => void;
/** Crop mode. Armed from the preview toolbar, the Clip panel, or a
* double-click on a croppable selection; while armed, edge handles on the
* selection adjust a non-destructive clip-path inset. `available` is
* published by DomEditOverlay when the selection can be cropped. */
cropMode: boolean;
setCropMode: (active: boolean) => void;
cropAvailable: boolean;
setCropAvailable: (available: boolean) => void;
/** Multi-select: additional selected elements beyond selectedElementId. */
selectedElementIds: Set<string>;
toggleSelectedElementId: (id: string) => void;
@@ -259,11 +250,6 @@ export const usePlayerStore = create<PlayerState>((set, get) => ({
setMotionPathCreateAvailable: (available) => set({ motionPathCreateAvailable: available }),
autoKeyframeEnabled: true,
setAutoKeyframeEnabled: (enabled) => set({ autoKeyframeEnabled: enabled }),
cropMode: false,
setCropMode: (active) => set({ cropMode: active }),
cropAvailable: false,
setCropAvailable: (available) =>
set(available ? { cropAvailable: true } : { cropAvailable: false, cropMode: false }),
selectedElementIds: new Set<string>(),
toggleSelectedElementId: (id: string) =>