Mixins / foldkit-mixins-ui
ImageCropperSlots
const · packages/mixins-ui/src/imageCropper.ts:49
const ImageCropperSlots: Slots.Contract<{ readonly root: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly [Attr.AttrToken<"role">], readonly Slot.RequirementName[], boolean>; readonly label: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly viewport: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly stage: Slot.UnnamedSlot<Capability.Capability<"Container", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly pan: Slot.UnnamedSlot<Capability.Capability<"Draggable", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>; readonly image: Slot.UnnamedSlot<Capability.Capability<"Base", readonly []>, readonly Slot.EventName[], reado …;An image cropper after Zag's: the image fitted in a viewport, a crop
selection over it that a drag moves and eight handles resize, the rest
of the image veiled, zoom (a Slider, the wheel, + and -), quarter
turns, an aspect-ratio lock and a round crop. Export draws the crop on a
canvas and answers with it as a data URL.
The crop is a small Model of this module's in the image's own pixels, of
the image as turned: a 4000 by 3000 photo turned a quarter is 3000 wide,
and a crop of its left half is { x: 0, y: 0, width: 1500, height: 4000 }.
The view measures the viewport (Resize) and reads the image's natural
size when it loads, and every drag reaches update as the Move Mount's
distance from where the pointer went down, which update applies to the
crop the drag began with, so a drag never drifts.
Zoom keeps the selection where it is on screen and magnifies the image under it, so zooming in crops less of the image. While zoomed in, a drag on the image outside the selection pans: the view and the crop move together over the image. The selection stays inside the image and inside what the viewport shows.
The selection is one focusable role="slider" (Zag's "2D slider"; the APG
has no cropper) whose aria-valuetext says the crop: the arrows move it by
a pixel of the screen (Shift by ten), Alt with the arrows resizes it from
its far edges, and + and - zoom. The keys are physical, as the plane
is, in either direction. The handles are for the pointer and hidden from
assistive technology.
The viewport carries the geometry for the recipe as custom properties in
pixels: --fk-cropper-x, -y, -w, -h (the selection),
--fk-cropper-image-x, -y, -w, -h (the turned image's box),
--fk-cropper-natural-w, -h (the image element before it is turned) and
--fk-cropper-rotation.