{"id":20782388,"url":"https://github.com/devtheorem/cropt","last_synced_at":"2026-05-10T20:25:01.318Z","repository":{"id":205545008,"uuid":"714461157","full_name":"devtheorem/cropt","owner":"devtheorem","description":"A lightweight JavaScript image cropper","archived":false,"fork":false,"pushed_at":"2024-11-07T17:02:07.000Z","size":6386,"stargazers_count":28,"open_issues_count":1,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-12T09:18:35.737Z","etag":null,"topics":["avatar","crop-image","croppie","profile-image"],"latest_commit_sha":null,"homepage":"https://devtheorem.github.io/cropt/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Foliotek/Croppie","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devtheorem.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-04T23:01:02.000Z","updated_at":"2024-11-10T09:46:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"174ddb40-d47f-4743-b951-f6ec7a235b20","html_url":"https://github.com/devtheorem/cropt","commit_stats":{"total_commits":428,"total_committers":67,"mean_commits":6.388059701492537,"dds":"0.40654205607476634","last_synced_commit":"dbc3a52c61c3b6919e5c92b454ad89f2b4b9d62c"},"previous_names":["theodorejb/croppie-ts","theodorejb/cropt","devtheorem/cropt"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtheorem%2Fcropt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtheorem%2Fcropt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtheorem%2Fcropt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devtheorem%2Fcropt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devtheorem","download_url":"https://codeload.github.com/devtheorem/cropt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251791168,"owners_count":21644356,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["avatar","crop-image","croppie","profile-image"],"created_at":"2024-11-17T14:05:56.585Z","updated_at":"2026-05-10T20:25:01.312Z","avatar_url":"https://github.com/devtheorem.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cropt\r\n\r\nA delightful image cropper optimized for both mobile and desktop use.\r\n\r\n* Includes TypeScript definitions.\r\n* Published as a native ES module.\r\n* Zero dependencies.\r\n* Originally based on [Croppie](https://github.com/Foliotek/Croppie), but rewritten in TypeScript with a simpler API and lots of bug fixes and polish.\r\n\r\n## Installation\r\n\r\n```sh\r\nnpm install cropt\r\n```\r\n\r\n## Usage\r\n\r\n1. Include the `src/cropt.css` stylesheet on your page.\r\n2. Add a `\u003cdiv\u003e` element with a unique ID to your HTML to hold the Cropt instance.\r\n3. Import Cropt and instantiate it with a reference to the `\u003cdiv\u003e` element and an object for options.\r\n4. Bind to an image URL.\r\n\r\n```html\r\n\u003cdiv id=\"cropper\"\u003e\u003c/div\u003e\r\n```\r\n\r\n```javascript\r\nimport { Cropt } from \"cropt\";\r\nimport \"cropt/src/cropt.css\";\r\n\r\nlet croptEl = document.getElementById('cropper');\r\nlet cropt = new Cropt(croptEl, {\r\n    viewport: { width: 250, height: 250 },\r\n});\r\ncropt.bind(\"path/to/image.jpg\");\r\n```\r\n\r\n### Binding from a file input\r\n\r\nTo let users pick an image from their device, bind from a file `\u003cinput\u003e` element's `change` event using `URL.createObjectURL()`:\r\n\r\n```html\r\n\u003cinput type=\"file\" id=\"fileInput\" accept=\"image/*\" /\u003e\r\n```\r\n\r\n```javascript\r\ndocument.getElementById('fileInput').addEventListener('change', (e) =\u003e {\r\n    const file = e.target.files[0];\r\n    if (!file) return;\r\n\r\n    const url = URL.createObjectURL(file);\r\n    cropt.bind(url).then(() =\u003e URL.revokeObjectURL(url));\r\n});\r\n```\r\n\r\nThe object URL can be revoked after binding because Cropt has already loaded the image data into the DOM at that point.\r\n\r\n### Uploading the cropped image\r\n\r\nUse `toBlob()` to get the cropped image as a `Blob`, then send it to your server with `fetch`:\r\n\r\n```javascript\r\nasync function upload() {\r\n    const blob = await cropt.toBlob(500, \"image/webp\"); // longest side scaled to 500px\r\n\r\n    const body = new FormData();\r\n    body.append('image', blob, 'crop.webp');\r\n\r\n    await fetch('/upload', { method: 'POST', body });\r\n}\r\n```\r\n\r\n### Sizing\r\n\r\nThe Cropt boundary defaults to 320px wide and 320px high.\r\nTo customize this, override the `.cropt-container .cr-boundary` width and height via CSS.\r\n\r\n## Options\r\n\r\n### `mouseWheelZoom`\r\n\r\nType: `\"off\" | \"on\" | \"ctrl\"`  \r\nDefault value: `\"on\"`\r\n\r\nIf set to `\"off\"`, the mouse wheel cannot be used to zoom in and out of the image.\r\nIf set to `\"ctrl\"`, the mouse wheel will only zoom in and out while the CTRL key is pressed.\r\n\r\n### `viewport`\r\n\r\nType: `{ width: number, height: number, borderRadius: string }`  \r\nDefault value: `{ width: 220, height: 220, borderRadius: \"0px\" }`\r\n\r\nDefines the size and shape of the crop box.\r\nFor a circle shape, set the border radius to `\"50%\"`.\r\n\r\n### `enableResize`\r\n\r\nType: `boolean`  \r\nDefault value: `false`\r\n\r\nIf set to `true`, resize handles are shown on the edges of the viewport, allowing the user to adjust its size.\r\n\r\n### `zoomerInputClass`\r\n\r\nType: `string`  \r\nDefault value: `\"cr-slider\"`\r\n\r\nOptionally set a different class on the zoom range input to customize styling (e.g. set to `\"form-range\"` when using Bootstrap).\r\n\r\n## Methods\r\n\r\n### `bind(src: string, state: CroptState | number | null = null): Promise\u003cvoid\u003e`\r\n\r\nTakes an image URL as the first argument. Returns a `Promise` which resolves when the image has been loaded and state is initialized.\r\n\r\nThe optional second argument can be:\r\n- A `CroptState` object (returned by `getState()`) to restore a previously saved crop position, zoom, and viewport size.\r\n- A `number` to set only the initial zoom level.\r\n\r\n### `getState(): CroptState`\r\n\r\nReturns the current crop state as a `CroptState` object with fields `x`, `y`, `zoom`, `width`, and `height`.\r\nThis can be stored alongside the original image and later passed to `bind()` to restore the crop position, zoom level, and viewport size.\r\n\r\n```javascript\r\n// Save state when the user is done cropping\r\nconst state = cropt.getState();\r\n\r\n// Later, restore the same crop position on the same image\r\ncropt.bind(\"path/to/image.jpg\", state);\r\n```\r\n\r\n### `destroy(): void`\r\n\r\nDeconstructs a Cropt instance and removes the elements from the DOM.\r\n\r\n### `refresh(): void`\r\n\r\nRecalculate points for the image. Necessary if the instance was bound while hidden, or if it has been hidden and re-shown.\r\n\r\n### `toCanvas(size: number | null = null): Promise\u003cHTMLCanvasElement\u003e`\r\n\r\nReturns a `Promise` resolving to an `HTMLCanvasElement` object for the cropped image.\r\nIf `size` is specified, the cropped image will be scaled with its longest side set to this value.\r\n\r\n### `toBlob(size: number | null = null, type = \"image/webp\", quality = 1): Promise\u003cBlob\u003e`\r\n\r\nReturns a `Promise` resolving to a `Blob` object for the cropped image.\r\nIf `size` is specified, the cropped image will be scaled with its longest side set to this value.\r\nThe `type` and `quality` parameters are passed directly to the corresponding\r\n[`HTMLCanvasElement.toBlob()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) method parameters.\r\n\r\n### `setOptions(options: CroptOptions): void`\r\n\r\nAllows options to be dynamically changed on an existing Cropt instance.\r\n\r\n### `setZoom(value: number): void`\r\n\r\nSet the zoom of a Cropt instance. The value must be between 0 and 1, and is clamped to the min/max zoom calculated for the current image.\r\n\r\n## Visibility and binding\r\n\r\nCropt is dependent on its container being visible when the bind method is called.\r\nThis can be an issue when your component is inside a modal that isn't shown. Consider the Bootstrap modal, for example:\r\n\r\n```javascript\r\nconst cropEl = document.getElementById('my-cropt');\r\nconst c = new Cropt(cropEl, opts);\r\nconst myModal = document.getElementById('my-modal');\r\n\r\nmyModal.addEventListener('shown.bs.modal', () =\u003e {\r\n    c.bind(\"my/image.jpg\");\r\n});\r\n```\r\n\r\nIf your Cropt instance is inside a modal, make sure `bind()` is called after the modal finishes opening.\r\n\r\nIf a Cropt instance needs to be hidden and then re-shown, call the `refresh()` method to recalculate properties for the displayed image.\r\n\r\n## Browser support\r\n\r\nCropt is tested in the following browsers:\r\n\r\n* Firefox\r\n* Safari\r\n* Chrome\r\n* Edge\r\n\r\nCropt should also work in any other modern browser using an engine based on Gecko, WebKit, or Chromium.\r\n\r\n## License\r\n\r\nMIT\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevtheorem%2Fcropt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevtheorem%2Fcropt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevtheorem%2Fcropt/lists"}