Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2164b79
Clean up (es6 optimizations, memory leak on listeners)
mindflowgo Dec 21, 2025
9105a90
Added resize bar functionality
mindflowgo Dec 21, 2025
694dead
Update README with new 'resizeBars' option
mindflowgo Dec 21, 2025
d6c3ae7
Update README with enhancements and clarifications
mindflowgo Dec 21, 2025
9546f42
Added getCropInfo() to read crop details
mindflowgo Dec 21, 2025
b284f91
Merge branch 'master' of github.com:mindflowgo/cropt
mindflowgo Dec 21, 2025
c488900
Added get() method, and bind-set to restore the image placement
mindflowgo Dec 22, 2025
65bc698
Reverted demo; left get()/set there but comented out.
mindflowgo Dec 22, 2025
ffb1abc
Reverted demo; left get()/set there but comented out.
mindflowgo Dec 22, 2025
44c25e4
Optimized transform management.
mindflowgo Dec 23, 2025
c7782ae
Small fixes for final release with resizeBrs.
mindflowgo Dec 23, 2025
3267976
Switched eventListener cleanup to AbortController()
mindflowgo Dec 23, 2025
f277977
Updated demo code to demonstrate presets & resizeBars. Multi-tab demo…
mindflowgo Dec 23, 2025
a0469cf
Cleanup of demo code
mindflowgo Dec 23, 2025
c6a646f
Added rotation feature & updated demo #3.
mindflowgo Dec 23, 2025
3f70405
Tweaks to rotation code
mindflowgo Dec 23, 2025
351e5f3
Rounding in demo code
mindflowgo Dec 23, 2025
1a434b2
Work on demo code
mindflowgo Dec 23, 2025
785e58e
Prettify everything
mindflowgo Dec 23, 2025
43324af
Added options to disable zoom slider, revised option names
mindflowgo Dec 23, 2025
7906d5e
Fixed up the keyboard navigation code and keyboard enablement option
mindflowgo Dec 23, 2025
94c0271
Include a CONTRIBUTING.md file
mindflowgo Dec 23, 2025
00fb593
Updating changelog + contributor
mindflowgo Dec 23, 2025
7dd52d5
Transparency handling added; bind() loads blob now (much faster)
mindflowgo Dec 25, 2025
7799e18
Reverted unnecessary change in loadImage()
mindflowgo Dec 25, 2025
536a260
Adjusting tooling for minified versions.
mindflowgo Dec 30, 2025
bd9755d
Fixes to make proper cross-platform package. CDN-compatible now. Mini…
mindflowgo Dec 31, 2025
40f0aa0
Bumped version
mindflowgo Dec 31, 2025
57d6606
Moved demo to docs for github publishing
mindflowgo Dec 31, 2025
d895958
Moved demo to /docs
mindflowgo Dec 31, 2025
078dc9f
Added package-lock.json
mindflowgo Dec 31, 2025
1eb2e8b
Update README for Cropt v2
mindflowgo Dec 31, 2025
fd7aa5a
Optimizing terser packaging.
mindflowgo Jan 2, 2026
ab1fab0
Merge branch 'master' of github.com:mindflowgo/cropt
mindflowgo Jan 2, 2026
0a824f2
Updating readme
mindflowgo Jan 2, 2026
e52f388
Fixed demo code
mindflowgo Jan 2, 2026
8e1066c
Fixed demo code
mindflowgo Jan 2, 2026
af3b1dc
Added react & svelte component wrappers
mindflowgo Jan 2, 2026
9c76b50
Added react & svelte component wrappers
mindflowgo Jan 2, 2026
3ba5b55
Cropt svelte component updates
mindflowgo Jan 2, 2026
65be610
Improved error messages and handling
mindflowgo Jan 2, 2026
2e2918c
Fix demo to use ?module
mindflowgo Jan 2, 2026
bc531a6
CSS changes: container now fits user-specified area
mindflowgo Jan 2, 2026
dfcdb19
Fixing css for toolbar
mindflowgo Jan 2, 2026
12ecca9
Added more documentation; css tweaks.
mindflowgo Jan 2, 2026
573ae44
Updated readme
mindflowgo Jan 2, 2026
5d032a2
Demo page changes
mindflowgo Jan 2, 2026
85f5f35
Fixed readme
mindflowgo Jan 2, 2026
0b8d6f0
Fixed terser packing
mindflowgo Jan 3, 2026
aae6d53
Package version update; fix in demo.
mindflowgo Jan 3, 2026
a7cbf14
Cross-browser vite compatibility tweak
mindflowgo Jan 4, 2026
292672d
Revise README
mindflowgo Jan 9, 2026
2148347
Cleared up example JS
mindflowgo Jan 9, 2026
dcf2217
Changing default viewport width/height to container-60px
mindflowgo Jan 9, 2026
c589226
Merge branch 'master' of github.com:mindflowgo/cropt
mindflowgo Jan 9, 2026
f29aa42
Package keywords updated + version
mindflowgo Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .github/workflows/node.js.yml

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ node_modules/
demo/build/
src/*.js
src/*.d.ts
dist/
pnpm-lock.yaml

4 changes: 4 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
src/
demo/styles.scss
Gruntfile.cjs
tsconfig.json
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Changelog
## [2.0.18] - 2026-01-08
- Adjusting viewport default size to be container - 60px (instead of 220px by 220px)

## [2.0.15] - 2026-01-02
- Included more documentation, small fixes and CSS tweaks.

## [2.0.4] - 2025-12-31
- Extended package options for use in browser, commonjs, etc.

## [2.0.0] - 2025-12-23
- Extended feature set: resizeBars, rotation.
- Fixed features (keyboard image movement)
- Added get() method to get viewport/crop info
- Added preset parameter for bind() to pass in viewport/transform options to restore crop arrangement

## [1.0.0] - 2024-12-01
### Changed
Expand Down
81 changes: 81 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Contributing to Cropt
First off, thank you for considering contributing to Cropt! It's people like you that make Cropt such a great tool.

## Acknowledgements
We thank our contributors for helping make Cropt even better:

[Foliotek/Croppie](https://github.com/Foliotek/Croppie)
Originally based on Croppie, but rewritten as a modern ES6

[Theodore Brown](https://github.com/devtheorem/)
- Simplified Croppie into this streamline solution.

[Filipe Laborde](https://github.com/mindflowgo/)
- Enhanced Cropt with Croppie-like resize handle grabbers, rotation, get() + preset restoring, and improved packaging.

## Quickstart
First, this is a community project, so the developers and contributors appreciate properly prepared contributions and help by others. Please review the code before making changes to keep with the format of the existing code.

### Pull Requests
Fork the repository on GitHub

Clone your fork locally:

```bash
git clone https://github.com/YOUR-USERNAME/cropt.git
cd cropt
npm install
npm run prepare
npm start
```

### Coding Standards
We use TypeScript for type safety. Please run your changes and submits through Prettier before submitting PR.

```
npm run format
```

Write self-documenting code with clear variable/function names; Add comments for complex logic.

### Project Structure
cropt/
├── src/ # Source code
| ├── cropt.css # Cropt CSS
| ├── cropt.ts # Cropt code
│ └── demo.ts # Demo javascript
├── docs/ # Documentation & Demos
├── tests/ # Test files (future?)
├── package.json
├── package.mjs # Builder script
└── README.md # new options & methods document here!

### Building and Testing
Test your changes thoroughly. Please try to keep existing behaviour and methods so it will be backwards compatible.

```bash
npm run build
npm start
```

### Documentation
Keep documentation up to date with code changes

Update README.md when adding new features

Add JSDoc comments for public APIs

Update demo examples when features warrant. Create another tab in the Demo page to showcase them.

### Reporting Issues
When reporting issues, please include:
- Clear description of the problem
- Steps to reproduce the issue
- Expected behavior vs Actual behavior
- Screenshots if applicable
- Browser/OS information

### Feature Requests
We welcome feature requests! Please provide links to other croppers that showcase the feature or screenshots to help us understand. Give us the use-case so we can understand better.

And finally, consider writing the feature yourself. Use AI to help!
36 changes: 0 additions & 36 deletions Gruntfile.cjs

This file was deleted.

1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ MIT License

Copyright (c) 2015 Foliotek Inc
Copyright (c) 2023 Theodore Brown
Copyright (c) 2026 Filipe Laborde-Basto

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
Expand Down
114 changes: 85 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,109 @@
# Cropt - lightweight JavaScript image cropper
# Cropt v2 - lightweight JavaScript image cropper
[Github](https://github.com/mindflowgo/cropt/)

Originally based on [Foliotek/Croppie](https://github.com/Foliotek/Croppie), but rewritten as a modern ES module with a simpler API, higher quality image scaling, and numerous other improvements.
Originally based on [Foliotek/Croppie](https://github.com/Foliotek/Croppie), but rewritten as a modern ES module with a simpler API, higher quality image scaling, and numerous other improvements by
[Devtheorem](https://devtheorem.github.io/cropt/).

It was extensively enhanced (but backwards compatible with v1) to include adjustable viewport, rotation,
keyboard handling, and various optimizations and bug fixes. And packed to work as browser install, commonJS, esm package, etc.


## Quick Start

- Look at the /docs directory for examples.
- Try our [codepen](https://codepen.io/mindflowgo/pen/QwEbegE).

## Installation

```
npm install cropt
npm install cropt2
```

## Running Demo

```
npm run build
npm start
```

## Usage

1. Include the `src/cropt.css` stylesheet on your page.
1. Include the `cropt.min.css` stylesheet on your page.
2. Add a `div` element to your HTML to hold the Cropt instance.
3. Import Cropt and bind it to an image:

```javascript
import { Cropt } from "cropt";
import Cropt from "cropt2";

let c = new Cropt(document.getElementById('demo'), options);
c.bind("path/to/image.jpg");
const presets = {};
const cropt = new Cropt(document.getElementById('demo'), presets);
cropt.bind("path/to/image.jpg");
```

### Sizing

The Cropt boundary defaults to 320px wide and 320px high.
To customize this, override the `.cropt-container .cr-boundary` width and height via CSS.
The Cropt boundary requires a minimum height of 100px but otherwise it will adjust to the size
of the container it is in. If toolbar (rotate, zoom) features, it builds a 32px high toolbar at
the bottom.

## Options

### `mouseWheelZoom`

Type: `"off" | "on" | "ctrl"`
Default value: `"on"`

If set to `"off"`, the mouse wheel cannot be used to zoom in and out of the image. If set to `"ctrl"`, the mouse wheel will only zoom in and out while the CTRL key is pressed.

### `viewport`

Type: `{ width: number, height: number, borderRadius: string }`
Default value: `{ width: 220, height: 220, borderRadius: "0px" }`
Default value: `{ width: [container]-60px, height: [container]-60px, borderRadius: "0px" }`

Defines the size and shape of the crop box.
For a circle shape, set the border radius to `"50%"`.

### `enableZoomSlider`

Type: `boolean`
Default value: `true`

Toggle if hiding the zoom slider.

### `enableKeypress`

Type: `boolean`
Default value: `true`

Toggle if allow listening for keyboard arrow keys for moving image. Will ignore if active element is a user input one (input box, text area, button).

### `resizeBars`

Type: `boolean`
Default value: `false`

Optionally to show resize handles (grab-bars) to adjust the viewport width/height.

### `enableRotateBtns`

Type: `boolean`
Default value: `false`

Toggle if showing rotation buttons beside the zoom slider bar. If both are off (enableZoomSlider and this), the toolbar is hidden.

### `mouseWheelZoom`

Type: `"off" | "on" | "ctrl"`
Default value: `"on"`

If set to `"off"`, the mouse wheel cannot be used to zoom in and out of the image. If set to `"ctrl"`, the mouse wheel will only zoom in and out while the CTRL key is pressed.

### `zoomerInputClass`

Type: `string`
Default value: `"cr-slider"`

Optionally set a different class on the zoom range input to customize styling (e.g. set to `"form-range"` when using Bootstrap).


## Methods

### `bind(src: string, zoom: number | null = null): Promise<void>`
### `bind(src: string, preset: number | { transform, viewport }): Promise<void>`

Takes an image URL as the first argument, and an optional initial zoom value. Returns a `Promise` which resolves when the image has been loaded and state is initialized.
Takes an image URL as the first argument, and an optional initial zoom value OR preset restore data for image placement in viewport. Returns a `Promise` which resolves when the image has been loaded and state is initialized.

### `destroy(): void`

Expand All @@ -72,6 +121,15 @@ Returns a `Promise` resolving to an `HTMLCanvasElement` object for the cropped i

Returns a Promise resolving to a `Blob` object for the cropped image. If `size` is specified, the cropped image will be scaled with its longest side set to this value. The `type` and `quality` parameters are passed directly to the corresponding [HTMLCanvasElement.toBlob()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) method parameters.

### `get(): { crop: { left, top, right, bottom }, transform: { x, y, scale, rotate, origin: {x, y}}, viewport: { width, height, borderRadius } }`
Returns information about the current crop state (all `numbers`):

- crop: Crop coordinates on the original image (left, top, right, bottom in pixels). (Note: if rotation present, image must be rotated FIRST then crop coordinates will apply)
- transform: Information for re-placement of image within viewport
- viewport: Final viewport dimensions and styling (width, height, borderRadius)

Useful for server-side cropping or saving user selections.

### `setOptions(options: CroptOptions): void`

Allows options to be dynamically changed on an existing Cropt instance.
Expand All @@ -80,19 +138,13 @@ Allows options to be dynamically changed on an existing Cropt instance.

Set the zoom of a Cropt instance. The value must be between 0 and 1, and is restricted to the min/max set by Cropt.

## Visibility and binding
### `setRotation(value: number): void`

Cropt is dependent on its container being visible when the bind method is called. This can be an issue when your component is inside a modal that isn't shown. Consider the Bootstrap modal, for example:
Set a rotation factor (0, 90, 180, 270) to the image.

```javascript
const cropEl = document.getElementById('my-cropt');
const c = new Cropt(cropEl, opts);
const myModal = document.getElementById('my-modal');
## Visibility and binding

myModal.addEventListener('shown.bs.modal', () => {
c.bind("my/image.jpg");
});
```
Cropt is dependent on its container being **visible** when the bind method is called. This can be an issue when your component is inside a modal or block that isn't shown (ex. style = display:none).

If you have issues getting the correct result, and your Cropt instance is shown inside a modal, try taking it out of the modal and see if the issue persists. If not, make sure that your bind method is called after the modal finishes opening.

Expand All @@ -106,9 +158,13 @@ Cropt is tested in the following browsers:
* Safari
* Chrome
* Edge
* Mobile Safari

Cropt should also work in any other modern browser using an engine based on Gecko, WebKit, or Chromium.

## License

MIT



Loading