@lemonadejs/cropper 5.1.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -26
- package/dist/index.js +45 -29
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -15,7 +15,6 @@ A lightweight, powerful **JavaScript image cropper** and photo editor component
|
|
|
15
15
|
- **TypeScript Support**: Full TypeScript definitions included
|
|
16
16
|
- **Framework Integration**: Works with vanilla JavaScript, React, Vue, and any modern framework
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
## Installation
|
|
20
19
|
|
|
21
20
|
### NPM Installation
|
|
@@ -35,7 +34,7 @@ npm install @lemonadejs/cropper
|
|
|
35
34
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.css" />
|
|
36
35
|
|
|
37
36
|
<!-- LemonadeJS Cropper Plugin -->
|
|
38
|
-
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.js"></script>
|
|
37
|
+
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.min.js"></script>
|
|
39
38
|
```
|
|
40
39
|
|
|
41
40
|
## Quick Start Example
|
|
@@ -49,7 +48,7 @@ npm install @lemonadejs/cropper
|
|
|
49
48
|
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
|
|
50
49
|
<script src="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.js"></script>
|
|
51
50
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/cropper/cropper.min.css" />
|
|
52
|
-
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.js"></script>
|
|
51
|
+
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/cropper/dist/index.min.js"></script>
|
|
53
52
|
</head>
|
|
54
53
|
<body>
|
|
55
54
|
<div id="root"></div>
|
|
@@ -146,7 +145,7 @@ cropper.setValue({
|
|
|
146
145
|
// Get cropped image data
|
|
147
146
|
const imageData = cropper.getValue();
|
|
148
147
|
console.log(imageData);
|
|
149
|
-
// Output:
|
|
148
|
+
// Output: { file: 'blob:...', content: 'data:image/png;base64,...', extension: 'png' }
|
|
150
149
|
```
|
|
151
150
|
|
|
152
151
|
## Usage Examples
|
|
@@ -164,9 +163,9 @@ const profileCropper = Cropper(document.getElementById('profile-editor'), {
|
|
|
164
163
|
async function uploadProfilePicture() {
|
|
165
164
|
const data = profileCropper.getValue();
|
|
166
165
|
|
|
167
|
-
if (data && data
|
|
166
|
+
if (data && data.content) {
|
|
168
167
|
const formData = new FormData();
|
|
169
|
-
const response = await fetch(data
|
|
168
|
+
const response = await fetch(data.content);
|
|
170
169
|
const blob = await response.blob();
|
|
171
170
|
formData.append('profile_picture', blob, 'profile.png');
|
|
172
171
|
|
|
@@ -214,13 +213,13 @@ const responsiveCropper = Cropper(document.getElementById('mobile-editor'), {
|
|
|
214
213
|
|
|
215
214
|
### Options
|
|
216
215
|
|
|
217
|
-
| Property | Type
|
|
218
|
-
|
|
219
|
-
| `width` | number
|
|
220
|
-
| `height` | number
|
|
221
|
-
| `original` | boolean
|
|
222
|
-
| `name` | string
|
|
223
|
-
| `value` | ImageData
|
|
216
|
+
| Property | Type | Default | Description |
|
|
217
|
+
|------------|-----------|-----------|----------------------------------------|
|
|
218
|
+
| `width` | number | 300 | Width of the crop area in pixels |
|
|
219
|
+
| `height` | number | 240 | Height of the crop area in pixels |
|
|
220
|
+
| `original` | boolean | false | Whether to preserve the original image |
|
|
221
|
+
| `name` | string | undefined | Name attribute for form integration |
|
|
222
|
+
| `value` | ImageData | null | Initial image data |
|
|
224
223
|
|
|
225
224
|
### Methods
|
|
226
225
|
|
|
@@ -229,10 +228,10 @@ Retrieve the current cropped image data and metadata.
|
|
|
229
228
|
|
|
230
229
|
```javascript
|
|
231
230
|
const data = cropper.getValue();
|
|
232
|
-
// Returns:
|
|
231
|
+
// Returns: { file: 'blob:...', content: 'data:image/...', extension: 'png' }
|
|
233
232
|
```
|
|
234
233
|
|
|
235
|
-
**Returns:** `ImageData
|
|
234
|
+
**Returns:** `ImageData` - Object containing image data with file URL, content, and extension
|
|
236
235
|
|
|
237
236
|
#### setValue(data)
|
|
238
237
|
Set or update the image in the cropper.
|
|
@@ -252,7 +251,7 @@ cropper.setValue(null);
|
|
|
252
251
|
```
|
|
253
252
|
|
|
254
253
|
**Parameters:**
|
|
255
|
-
- `data` (string | ImageData |
|
|
254
|
+
- `data` (string | ImageData | null): Image URL, data object, or null to clear
|
|
256
255
|
|
|
257
256
|
#### open()
|
|
258
257
|
Programmatically open the cropper modal interface.
|
|
@@ -265,18 +264,14 @@ cropper.open();
|
|
|
265
264
|
Launch the file picker modal to allow users to select a new photo.
|
|
266
265
|
|
|
267
266
|
```javascript
|
|
268
|
-
|
|
269
|
-
document.querySelector('.upload-btn').addEventListener('click', () => {
|
|
270
|
-
// Note: This is handled internally by the cropper UI
|
|
271
|
-
});
|
|
267
|
+
cropper.uploadPhoto();
|
|
272
268
|
```
|
|
273
269
|
|
|
274
270
|
#### deletePhoto()
|
|
275
271
|
Remove the current image from the cropper container.
|
|
276
272
|
|
|
277
273
|
```javascript
|
|
278
|
-
|
|
279
|
-
// The cropper automatically resets when the image is deleted
|
|
274
|
+
cropper.deletePhoto();
|
|
280
275
|
```
|
|
281
276
|
|
|
282
277
|
#### setControls(state)
|
|
@@ -307,15 +302,16 @@ interface ImageData {
|
|
|
307
302
|
content?: string; // Base64 or data URL content
|
|
308
303
|
extension?: string; // File extension (e.g., 'jpg', 'png')
|
|
309
304
|
original?: string; // Original image URL (if preserved)
|
|
305
|
+
guid?: string;
|
|
310
306
|
}
|
|
311
307
|
```
|
|
312
308
|
|
|
313
309
|
## Related Projects
|
|
314
310
|
|
|
315
311
|
- **[LemonadeJS](https://lemonadejs.com)** - Reactive micro JavaScript library
|
|
312
|
+
- **[Jspreadsheet](https://jspreadsheet.com)** - JavaScript data grid and spreadsheet component
|
|
313
|
+
- **[CalendarJS](https://calendarjs.com)** - JavaScript calendar, schedule and timeline components
|
|
316
314
|
- **[jSuites](https://jsuites.net)** - JavaScript plugins and web components collection
|
|
317
|
-
- **[jSpreadsheet](https://jspreadsheet.com)** - JavaScript data grid and spreadsheet component
|
|
318
|
-
|
|
319
315
|
|
|
320
316
|
## License
|
|
321
317
|
|
|
@@ -323,7 +319,7 @@ MIT License
|
|
|
323
319
|
|
|
324
320
|
## Support & Community
|
|
325
321
|
|
|
326
|
-
- **Documentation**: [https://lemonadejs.com/plugins/cropper](https://lemonadejs.com/plugins/cropper)
|
|
322
|
+
- **Documentation**: [https://lemonadejs.com/docs/plugins/image-cropper](https://lemonadejs.com/docs/plugins/image-cropper)
|
|
327
323
|
- **GitHub Issues**: Report bugs and request features
|
|
328
324
|
- **Community**: Join our community for support and discussions
|
|
329
325
|
- **Website**: [https://lemonadejs.com](https://lemonadejs.com)
|
|
@@ -331,4 +327,3 @@ MIT License
|
|
|
331
327
|
## Contributing
|
|
332
328
|
|
|
333
329
|
Contributions are welcome! Please feel free to submit pull requests or open issues.
|
|
334
|
-
|
package/dist/index.js
CHANGED
|
@@ -123,7 +123,6 @@ if (typeof(cropper) === 'undefined') {
|
|
|
123
123
|
const updatePhoto = () => {
|
|
124
124
|
// Checks if cropper container is editable
|
|
125
125
|
if (self.cropperArea.classList.contains('jcrop_edition')) {
|
|
126
|
-
self.image.innerHTML = '';
|
|
127
126
|
// Create image with metadata
|
|
128
127
|
const newImage = crop.getCroppedImage();
|
|
129
128
|
// Callback for the blob
|
|
@@ -140,16 +139,8 @@ if (typeof(cropper) === 'undefined') {
|
|
|
140
139
|
if (original === true) {
|
|
141
140
|
data.original = crop.getImage().src;
|
|
142
141
|
}
|
|
143
|
-
// Update file to blob
|
|
144
|
-
newImage.src = filename;
|
|
145
|
-
// Integration with
|
|
146
|
-
if (self.name) {
|
|
147
|
-
newImage.classList.remove('jfile');
|
|
148
|
-
}
|
|
149
142
|
// Value
|
|
150
|
-
self.value =
|
|
151
|
-
// Append new image
|
|
152
|
-
self.image.appendChild(newImage);
|
|
143
|
+
self.value = data;
|
|
153
144
|
}
|
|
154
145
|
// Create image
|
|
155
146
|
crop.getCroppedAsBlob(createImage);
|
|
@@ -170,8 +161,6 @@ if (typeof(cropper) === 'undefined') {
|
|
|
170
161
|
crop.reset();
|
|
171
162
|
// Disable controls
|
|
172
163
|
self.setControls(false);
|
|
173
|
-
// Reset from container
|
|
174
|
-
self.image.innerHTML = '';
|
|
175
164
|
// Reset container
|
|
176
165
|
self.value = '';
|
|
177
166
|
}
|
|
@@ -211,19 +200,11 @@ if (typeof(cropper) === 'undefined') {
|
|
|
211
200
|
}
|
|
212
201
|
}
|
|
213
202
|
|
|
214
|
-
if (data.file) {
|
|
215
|
-
const img = document.createElement('img');
|
|
216
|
-
img.setAttribute('src', data.file);
|
|
217
|
-
img.setAttribute('tabindex', -1);
|
|
218
|
-
self.image.innerHTML = '';
|
|
219
|
-
self.image.appendChild(img);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
203
|
if (data.original) {
|
|
223
204
|
crop.addFromFile(data.original);
|
|
224
205
|
}
|
|
225
206
|
|
|
226
|
-
self.value =
|
|
207
|
+
self.value = data;
|
|
227
208
|
}
|
|
228
209
|
}
|
|
229
210
|
|
|
@@ -273,12 +254,47 @@ if (typeof(cropper) === 'undefined') {
|
|
|
273
254
|
}
|
|
274
255
|
});
|
|
275
256
|
|
|
257
|
+
onchange((prop) => {
|
|
258
|
+
let image = self.value;
|
|
259
|
+
let filename = null;
|
|
260
|
+
|
|
261
|
+
if (Array.isArray(self.value)) {
|
|
262
|
+
image = self.value[0];
|
|
263
|
+
}
|
|
264
|
+
const img = document.createElement('img');
|
|
265
|
+
img.setAttribute('tabindex', -1);
|
|
266
|
+
self.image.textContent = '';
|
|
267
|
+
// Integration with
|
|
268
|
+
if (self.name) {
|
|
269
|
+
img.classList.remove('jfile');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (image) {
|
|
273
|
+
if (typeof image === 'string') {
|
|
274
|
+
filename = image;
|
|
275
|
+
} else if (typeof image === 'object') {
|
|
276
|
+
filename = image.file;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (filename) {
|
|
281
|
+
if (typeof self.onbeforeloadimage === 'function') {
|
|
282
|
+
let ret = self.onbeforeloadimage(self, filename, img);
|
|
283
|
+
if (ret) {
|
|
284
|
+
filename = ret;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
img.setAttribute('src', filename);
|
|
288
|
+
self.image.appendChild(img);
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
|
|
276
292
|
track('value');
|
|
277
293
|
|
|
278
294
|
// Template
|
|
279
295
|
return render => render `<div name="{{self.name}}">
|
|
280
296
|
<div :ref='this.image' class="jphoto jcropper"></div>
|
|
281
|
-
<lm-modal draggable="true" closable="true" closed="true" width="800" height="
|
|
297
|
+
<lm-modal draggable="true" closable="true" closed="true" width="800" height="580" title="Photo Upload" icon="photo" :ref="self.modal">
|
|
282
298
|
<div :ready='self.createCropper' :ref='self.cropperArea'></div>
|
|
283
299
|
<div class="controls">
|
|
284
300
|
<div style="display: flex; justify-content: center; gap: 10px; text-align: center; border-top: 1px solid #ddd;">
|
|
@@ -287,13 +303,13 @@ if (typeof(cropper) === 'undefined') {
|
|
|
287
303
|
<label style="padding: 20px;">Brigthness<br><input type='range' min='-1' max='1' step='.05' value='0' :bind='self.brightness' oninput='${setBrightness}' class='jrange controls' disabled='disabled'></label>
|
|
288
304
|
<label style="padding: 20px;">Contrast<br><input type='range' min='-1' max='1' step='.05' value='0' :bind='self.contrast' oninput='${setContrast}' class='jrange controls' disabled='disabled'></label>
|
|
289
305
|
</div>
|
|
290
|
-
<div class='lm-row lm-
|
|
291
|
-
<div class='lm-column lm-
|
|
292
|
-
<input type='button' value='Save Photo' class='lm-button controls' style='
|
|
293
|
-
</div><div class='lm-column
|
|
294
|
-
<input type='button' value='Upload Photo' class='lm-button' style='
|
|
295
|
-
</div><div class='lm-column
|
|
296
|
-
<input type='button' value='Delete Photo' class='lm-button controls' style='
|
|
306
|
+
<div class='lm-row lm-p15' style='border-top: 1px solid #ddd'>
|
|
307
|
+
<div class='lm-column lm-f1'>
|
|
308
|
+
<input type='button' value='Save Photo' class='lm-button controls' style='width: 100%' onclick='${updatePhoto}' disabled='disabled'>
|
|
309
|
+
</div><div class='lm-column'>
|
|
310
|
+
<input type='button' value='Upload Photo' class='lm-button' style='width: 100%' onclick='${uploadPhoto}'>
|
|
311
|
+
</div><div class='lm-column' style='text-align:right'>
|
|
312
|
+
<input type='button' value='Delete Photo' class='lm-button controls' style='width: 100%' onclick='${deletePhoto}' disabled='disabled'>
|
|
297
313
|
</div>
|
|
298
314
|
</div>
|
|
299
315
|
</div>
|
package/package.json
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"javascript plugins"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"lemonadejs": "^5.3.
|
|
18
|
-
"@lemonadejs/studio": "^5.7.
|
|
17
|
+
"lemonadejs": "^5.3.3",
|
|
18
|
+
"@lemonadejs/studio": "^5.7.11",
|
|
19
19
|
"@jsuites/cropper": "^1.7.0"
|
|
20
20
|
},
|
|
21
21
|
"main": "dist/index.js",
|
|
22
|
-
"version": "
|
|
22
|
+
"version": "6.0.1"
|
|
23
23
|
}
|