ImageCropper.crop
function · packages/mixins-ui/src/imageCropper.ts:404
function crop(model: Model): Option.Option<Rect>The crop in whole image pixels, as Export draws it; none before the image loads.
Mixins / foldkit-mixins-ui
namespace · packages/mixins-ui/src/imageCropper.ts:1
export * as ImageCropper from './imageCropper.js'ImageCropper.cropfunction · packages/mixins-ui/src/imageCropper.ts:404
function crop(model: Model): Option.Option<Rect>The crop in whole image pixels, as Export draws it; none before the image loads.
ImageCropper.Exportconst · packages/mixins-ui/src/imageCropper.ts:418
const Export: Command.CommandDefinitionWithArgs<
'ImageCropper.Export',
{
image: Schema.String
natural: Schema.Struct<{
readonly width: Schema.Number
readonly height: Schema.Number
}>
rotation: Schema.Literals<readonly [0, 90, 180, 270]>
crop: Schema.Struct<{
readonly x: Schema.Number
readonly y: Schema.Number
readonly width: Schema.Number
readonly height: Schema.Number
}>
round: Schema.Boolean
type: Schema.Literals<readonly ['image/png', 'image/jpeg', 'image/webp']>
quality: Schema.Number
},
Effect.Effect<
| { readonly _tag: 'FailedExport'; readonly reason: string }
| {
readonly _tag: 'Exported'
readonly url: string
readonly width: number
readonly height: number
},
never,
never
>
>Draws the crop of the image the view drew (found by id) on a canvas, turned and, for a round shape, clipped to its ellipse with the corners left clear.
ImageCropper.ImageCropperLabelsinterface · packages/mixins-ui/src/imageCropper.ts:791
interface ImageCropperLabels {
readonly selection: string
readonly zoom: string
readonly rotateLeft: string
readonly rotateRight: string
readonly reset: string
readonly crop: (crop: Rect) => string
}The words a cropper says; each has an English default.
ImageCropper.ImageCropperSlotsconst · 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.
ImageCropper.ImageCropperViewinterface · packages/mixins-ui/src/imageCropper.ts:811
interface ImageCropperView<Message> {
readonly model: Model
readonly onMessage: (message: typeof Message.Type) => NoInfer<Message>
readonly label: string
readonly src: string
readonly crossOrigin?: 'anonymous' | 'use-credentials' | undefined
readonly controls?:
| {
readonly zoom?: boolean
readonly rotate?: boolean
readonly reset?: boolean
}
| undefined
readonly labels?: Partial<ImageCropperLabels> | undefined
readonly disabled?: boolean | undefined
readonly style?: NamedStyle<typeof ImageCropperSlots> | undefined
readonly slider?: NamedStyle<typeof SliderSlots> | undefined
readonly mixins?: MixinList<Message> | undefined
}ImageCropper.initfunction · packages/mixins-ui/src/imageCropper.ts:321
function init(options: {
readonly id: string
readonly aspect?: number | undefined
readonly shape?: Shape | undefined
readonly crop?: Rect | undefined
readonly min?: Size | undefined
readonly maxZoom?: number | undefined
}): ModelImageCropper.Messageconst · packages/mixins-ui/src/imageCropper.ts:352
const Message: MessageUnion<{
readonly MeasuredViewport: {
readonly width: Schema.Number
readonly height: Schema.Number
}
readonly LoadedImage: {
readonly width: Schema.Number
readonly height: Schema.Number
}
readonly StartedDrag: {
readonly part: Schema.Literals<
readonly [
...('s' | 'w' | 'n' | 'ne' | 'e' | 'se' | 'sw' | 'nw')[],
'selection',
'image',
]
>
}
readonly Dragged: {
readonly part: Schema.Literals<
readonly [
...('s' | 'w' | 'n' | 'ne' | 'e' | 'se' | 'sw' | 'nw')[],
'selection',
'image',
]
>
readonly deltaX: Schema.Number
readonly deltaY: Schema.Number
}
readonly EndedDrag: {}
readonly Wheeled: { readonly deltaY: Schema.Number }
readonly PressedKey: {
readonly key: Schema.String
readonly shift: Schema.Boolean
readonly alt: Schema.Boolean
}
readonly ChangedZoom: { readonly zoom: Schema.Number }
readonly Turned: { readonly clockwise: Schema.Boolean }
readonly ChangedAspect: {
readonly aspect: Schema.OptionFromNullOr<Schema.Number>
}
readonly Reset: {}
readonly RequestedExport: {
readonly type: Schema.Literals<
readonly ['image/png', 'image/jpeg', 'image/webp']
>
readonly quality: Schema.Number
}
readonly Exported: {
readonly url: Schema.String
readonly width: Schema.Number
readonly height: Schema.Number
}
readonly FailedExport: { readonly reason: Schema.String }
}>ImageCropper.Modelconst · packages/mixins-ui/src/imageCropper.ts:297
const Model: Schema.Struct<{ readonly id: Schema.String; readonly shape: Schema.Literals<readonly ["rectangle", "round"]>; readonly aspect: Schema.OptionFromNullOr<Schema.Number>; readonly min: Schema.Struct<{ readonly width: Schema.Number; readonly height: Schema.Number; }>; readonly zoom: Schema.Number; readonly maxZoom: Schema.Number; readonly rotation: Schema.Literals<readonly [0, 90, 180, 270]>; readonly initial: Schema.OptionFromNullOr<Schema.Struct<{ readonly x: Schema.Number; readonly y: Schema.Number; readonly width: Schema.Number; readonly height: Schema.Number; }>>; readonly viewport: Schema.OptionFromNullOr<Schema.Struct<{ readonly width: Schema.Number; readonly height: Schema.Number; }>>; readonly image: Schema.OptionFromNullOr<Schema.Struct<{ readonly natural: Schema.Struct<{ readonly width: Schema.Number; readonly height: Schema.Number; }>; readonly crop: Schema.Struct<{ readonly x: Schema.Number; readonly y: Schema.Number; readonly width: Schema.Number; readonly height: Schema.Number; }>; readonly focus: Schema.Struct<{ readonly x: Schema.Number; readonly y: Schema.Number; }>; }>>; readonly drag: Schema.OptionFromNullOr<Schema.Struct<{ readonly part: Schema.Literals<readonly [...("s" | "w" | "n" | "ne" | "e" | "se" | "sw" | "nw")[], "selection", "image"]>; readonly crop: Schema.Struct<{ readonly x: Schema.Number; readonly y: Schema.Number; readonly width: Schema.Number; readonly height: Schema.Number; }>; readonly focus: Schema.Struct<{ readonly x: Schema.Number; readonly …;ImageCropper.Rectconst · packages/mixins-ui/src/imageCropper.ts:89
const Rect: Schema.Struct<{
readonly x: Schema.Number
readonly y: Schema.Number
readonly width: Schema.Number
readonly height: Schema.Number
}>A rectangle in the turned image's pixels.
ImageCropper.Rotationconst · packages/mixins-ui/src/imageCropper.ts:98
const Rotation: Schema.Literals<readonly [0, 90, 180, 270]>Quarter turns clockwise, in degrees.
ImageCropper.Shapeconst · packages/mixins-ui/src/imageCropper.ts:102
const Shape: Schema.Literals<readonly ['rectangle', 'round']>round crops the ellipse inside the rectangle, a circle at an aspect of 1.
ImageCropper.Sizeconst · packages/mixins-ui/src/imageCropper.ts:82
const Size: Schema.Struct<{
readonly width: Schema.Number
readonly height: Schema.Number
}>ImageCropper.updatefunction · packages/mixins-ui/src/imageCropper.ts:592
function update(model: Model, message: Message): Return<Model, Message>The cropper after message; the same Model when nothing changes.
ImageCropper.viewfunction · packages/mixins-ui/src/imageCropper.ts:837
function view<Outer>(
options: ImageCropperView<Outer>,
h: HtmlBuilder<Outer>,
): Html