Something went wrong. Try again.
headless React image cropper
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071import { type ComponentPropsWithoutRef, type Ref, type SyntheticEvent, useCallback, useEffect } from 'react';
import type { Size } from '../core/types.ts';
import { useCropper, useCropperState } from './context.ts';
export interface CropperImageProps extends ComponentPropsWithoutRef<'img'> { ref?: Ref<HTMLImageElement>;}
/** * positioned source image. * * @param props image element props. a new `src` resets the crop. * @returns the source image element. * @throws when rendered outside a `<Cropper.Root>`. */export const Image = (props: CropperImageProps) => { const { alt = '', height, onLoad, src, style, width, ...rest } = props; const { reportNaturalSize, setSource } = useCropper(); const layout = useCropperState((state) => state.image);
useEffect(() => { const naturalWidth = Number(width); const naturalHeight = Number(height); let naturalSize: Size | null = null; if (naturalWidth > 0 && naturalHeight > 0) { naturalSize = { width: naturalWidth, height: naturalHeight }; } setSource({ src, naturalSize }); }, [height, setSource, src, width]);
const handleLoad = useCallback( (e: SyntheticEvent<HTMLImageElement>) => { onLoad?.(e); const el = e.currentTarget; reportNaturalSize({ width: el.naturalWidth, height: el.naturalHeight }); }, [onLoad, reportNaturalSize], );
return ( <img {...rest} data-cropper-image="" src={src} alt={alt} width={width} height={height} draggable={false} onLoad={handleLoad} // oxlint-disable-next-line react-perf/jsx-no-new-object-as-prop style={{ position: 'absolute', left: 0, top: 0, width: `${layout.width}px`, height: `${layout.height}px`, maxWidth: 'none', maxHeight: 'none', transform: `translate3d(${layout.x}px, ${layout.y}px, 0) rotate(${layout.rotation * 90}deg)`, transformOrigin: 'center center', willChange: 'transform', userSelect: 'none', WebkitUserSelect: 'none', ...style, }} /> );};