@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.
Files changed (3) hide show
  1. package/README.md +21 -26
  2. package/dist/index.js +45 -29
  3. 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: [{ file: 'blob:...', content: 'data:image/png;base64,...', extension: 'png' }]
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[0]) {
166
+ if (data && data.content) {
168
167
  const formData = new FormData();
169
- const response = await fetch(data[0].content);
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 | Default | Description |
218
- |------------|-------------|-----------|----------------------------------------|
219
- | `width` | number | 300 | Width of the crop area in pixels |
220
- | `height` | number | 240 | Height of the crop area in pixels |
221
- | `original` | boolean | false | Whether to preserve the original image |
222
- | `name` | string | undefined | Name attribute for form integration |
223
- | `value` | ImageData[] | null | Initial image data |
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: [{ file: 'blob:...', content: 'data:image/...', extension: 'png' }]
231
+ // Returns: { file: 'blob:...', content: 'data:image/...', extension: 'png' }
233
232
  ```
234
233
 
235
- **Returns:** `ImageData[]` - Array containing image data with file URL, content, and extension
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 | ImageData[] | null): Image URL, data object, array of data objects, or null to clear
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
- // Trigger file upload dialog
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
- // Note: This method is available through the context menu and UI controls
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 = [data];
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 = [data];
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="570" title="Photo Upload" icon="photo" :ref="self.modal">
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-p20' style='border-top: 1px solid #ddd'>
291
- <div class='lm-column lm-p6 lm-f1'>
292
- <input type='button' value='Save Photo' class='lm-button controls' style='min-width: 140px;' onclick='${updatePhoto}' disabled='disabled'>
293
- </div><div class='lm-column lm-p6'>
294
- <input type='button' value='Upload Photo' class='lm-button' style='min-width: 140px;' onclick='${uploadPhoto}'>
295
- </div><div class='lm-column lm-p6' style='text-align:right'>
296
- <input type='button' value='Delete Photo' class='lm-button controls' style='min-width: 140px;' onclick='${deletePhoto}' disabled='disabled'>
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.2",
18
- "@lemonadejs/studio": "^5.7.0",
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": "5.1.0"
22
+ "version": "6.0.1"
23
23
  }