npm package: @lemonadejs/cropper
Description: LemonadeJS and jSuites cropper editor integration
Author: Contact
Latest version: 6.0.1

# JavaScript Image Cropper - LemonadeJS Cropper Plugin

A lightweight, powerful **JavaScript image cropper** and photo editor component built with [LemonadeJS](https://lemonadejs.com). Crop, resize, rotate, and adjust images directly in your web browser with this modern, reactive image editing solution.

## Key Features

- **Image Cropping**: Intuitive drag-and-drop interface for precise image cropping
- **Image Rotation**: Rotate images with smooth, real-time preview
- **Zoom Control**: Fine-grained zoom functionality from 0.1x to 5.45x
- **Image Adjustments**: Brightness and contrast controls for professional results
- **Responsive Design**: Automatically adapts to mobile and desktop screens
- **Modal Interface**: Clean, user-friendly modal dialog for editing
- **Blob Output**: Generates cropped images as blobs for easy upload
- **Original Image Preservation**: Optionally keep the original image alongside the cropped version
- **TypeScript Support**: Full TypeScript definitions included
- **Framework Integration**: Works with vanilla JavaScript, React, Vue, and any modern framework

## Installation

### NPM Installation

```bash
npm install @lemonadejs/cropper
```

### CDN Installation

```html
<!-- LemonadeJS Core -->
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>

<!-- jSuites Cropper (dependency) -->
<script src="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.css" />

<!-- LemonadeJS Cropper Plugin -->
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.min.js"></script>
```

## Quick Start Example

### Basic Image Cropper

```html
<!DOCTYPE html>
<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.css" />
    <script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.min.js"></script>
</head>
<body>
<div id="root"></div>

<script>
    const root = document.getElementById('root');
    const cropper = Cropper(root, {
        width: 300,
        height: 240
    });
</script>
</body>
</html>
```

### Using with LemonadeJS Component

```javascript
import lemonade from 'lemonadejs';
import Cropper from '@lemonadejs/cropper';

export default function MyApp() {
    const self = this;

    return `<div>
        <h1>Profile Picture Editor</h1>
        <Cropper
            width="400"
            height="300"
            :ref="self.cropper"
            original="true" />
        <button onclick="self.cropper.open()">Edit Photo</button>
    </div>`;
}
```

### React Integration

```javascript
import React, { useRef, useEffect } from 'react';
import Cropper from '@lemonadejs/cropper';

function PhotoEditor() {
    const cropperRef = useRef(null);
    const containerRef = useRef(null);

    useEffect(() => {
        if (containerRef.current) {
            cropperRef.current = Cropper(containerRef.current, {
                width: 400,
                height: 300,
                original: true
            });
        }

        return () => {
            // Cleanup if needed
        };
    }, []);

    const handleGetImage = () => {
        if (cropperRef.current) {
            const imageData = cropperRef.current.getValue();
            console.log('Image data:', imageData);
        }
    };

    return (
        <div>
            <div ref={containerRef}></div>
            <button onClick={handleGetImage}>Get Image Data</button>
        </div>
    );
}

export default PhotoEditor;
```

### Advanced Configuration

```javascript
const cropper = Cropper(document.getElementById('root'), {
    width: 500,          // Crop area width
    height: 400,         // Crop area height
    original: true,      // Preserve original image
    name: 'profile_pic'  // Form field name
});

// Set an image programmatically
cropper.setValue({
    file: 'https://example.com/image.jpg'
});

// Get cropped image data
const imageData = cropper.getValue();
console.log(imageData);
// Output: { file: 'blob:...', content: 'data:image/png;base64,...', extension: 'png' }
```

## Usage Examples

### Profile Picture Upload

```javascript
const profileCropper = Cropper(document.getElementById('profile-editor'), {
    width: 200,
    height: 200,
    original: true
});

// After user crops the image
async function uploadProfilePicture() {
    const data = profileCropper.getValue();

    if (data && data.content) {
        const formData = new FormData();
        const response = await fetch(data.content);
        const blob = await response.blob();
        formData.append('profile_picture', blob, 'profile.png');

        // Upload to server
        await fetch('/api/upload', {
            method: 'POST',
            body: formData
        });
    }
}
```

### E-commerce Product Image Editor

```javascript
const productCropper = Cropper(document.getElementById('product-images'), {
    width: 800,
    height: 600,
    original: true,  // Keep original for zoom functionality
    name: 'product_image'
});

// Handle multiple product images
function addProductImage(imageUrl) {
    productCropper.setValue({
        file: imageUrl,
        original: imageUrl
    });
}
```

### Responsive Mobile-Friendly Cropper

```javascript
// Automatically adjusts for mobile devices
const responsiveCropper = Cropper(document.getElementById('mobile-editor'), {
    width: window.innerWidth < 640 ? window.innerWidth - 40 : 600,
    height: window.innerWidth < 640 ? window.innerWidth - 40 : 450
});

// The cropper automatically adapts its interface for screens < 800px
```

## API Reference

### Options

| Property   | Type      | Default   | Description                            |
|------------|-----------|-----------|----------------------------------------|
| `width`    | number    | 300       | Width of the crop area in pixels       |
| `height`   | number    | 240       | Height of the crop area in pixels      |
| `original` | boolean   | false     | Whether to preserve the original image |
| `name`     | string    | undefined | Name attribute for form integration    |
| `value`    | ImageData | null      | Initial image data                     |

### Methods

#### getValue()
Retrieve the current cropped image data and metadata.

```javascript
const data = cropper.getValue();
// Returns: { file: 'blob:...', content: 'data:image/...', extension: 'png' }
```

**Returns:** `ImageData` - Object containing image data with file URL, content, and extension

#### setValue(data)
Set or update the image in the cropper.

```javascript
// Set image with URL
cropper.setValue({
    file: 'path/to/image.jpg',
    original: 'path/to/original.jpg'
});

// Set image with string
cropper.setValue('https://example.com/image.jpg');

// Clear the image
cropper.setValue(null);
```

**Parameters:**
- `data` (string | ImageData | null): Image URL, data object, or null to clear

#### open()
Programmatically open the cropper modal interface.

```javascript
cropper.open();
```

#### uploadPhoto()
Launch the file picker modal to allow users to select a new photo.

```javascript
cropper.uploadPhoto();
```

#### deletePhoto()
Remove the current image from the cropper container.

```javascript
cropper.deletePhoto();
```

#### setControls(state)
Enable or disable the editing controls (zoom, rotate, brightness, contrast).

```javascript
cropper.setControls(false); // Disable all controls
cropper.setControls(true);  // Enable all controls
```

**Parameters:**
- `state` (boolean): True to enable, false to disable

### Properties

| Property      | Type        | Description                                   |
|---------------|-------------|-----------------------------------------------|
| `brightness`  | number      | Current brightness adjustment value (-1 to 1) |
| `contrast`    | number      | Current contrast adjustment value (-1 to 1)   |
| `greyscale`   | number      | Current greyscale value (0 to 1)              |
| `cropperArea` | HTMLElement | Reference to the cropper area DOM element     |

### ImageData Interface

```typescript
interface ImageData {
    file: string;       // URL or blob URL to the image
    content?: string;   // Base64 or data URL content
    extension?: string; // File extension (e.g., 'jpg', 'png')
    original?: string;  // Original image URL (if preserved)
    guid?: string;
}
```

## Related Projects

- **[LemonadeJS](https://lemonadejs.com)** - Reactive micro JavaScript library
- **[Jspreadsheet](https://jspreadsheet.com)** - JavaScript data grid and spreadsheet component
- **[CalendarJS](https://calendarjs.com)** - JavaScript calendar, schedule and timeline components
- **[jSuites](https://jsuites.net)** - JavaScript plugins and web components collection

## License

MIT License

## Support & Community

- **Documentation**: [https://lemonadejs.com/docs/plugins/image-cropper](https://lemonadejs.com/docs/plugins/image-cropper)
- **GitHub Issues**: Report bugs and request features
- **Community**: Join our community for support and discussions
- **Website**: [https://lemonadejs.com](https://lemonadejs.com)

## Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues.