senangwebs-photobooth 1.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/.github/copilot-instructions.md +252 -0
- package/LICENSE.md +21 -0
- package/README.md +297 -0
- package/dist/styles.js +1 -0
- package/dist/swp.css +448 -0
- package/dist/swp.js +1 -0
- package/examples/customization.html +360 -0
- package/examples/index.html +54 -0
- package/package.json +32 -0
- package/spec.md +239 -0
- package/src/css/swp.css +447 -0
- package/src/js/swp.js +726 -0
- package/swp_preview.png +0 -0
- package/webpack.config.js +39 -0
package/dist/swp.css
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
@import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css);
|
|
2
|
+
/**
|
|
3
|
+
* SenangWebs Photobooth (SWP) - Styles
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/* Font Awesome */
|
|
8
|
+
|
|
9
|
+
/* Container */
|
|
10
|
+
.swp-container {
|
|
11
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
12
|
+
max-width: 1200px;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.swp-wrapper {
|
|
17
|
+
background: #ffffff;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
height: 100%;
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Toolbar */
|
|
25
|
+
.swp-toolbar {
|
|
26
|
+
display: flex;
|
|
27
|
+
gap: 8px;
|
|
28
|
+
padding: 8px;
|
|
29
|
+
background: #f8f9fa;
|
|
30
|
+
flex-wrap: wrap;
|
|
31
|
+
justify-content: space-between;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.swp-toolbar-group {
|
|
35
|
+
display: flex;
|
|
36
|
+
gap: 0px;
|
|
37
|
+
align-items: center;
|
|
38
|
+
border: 1px solid #dee2e6;
|
|
39
|
+
border-radius: 8px;
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.swp-toolbar-group .swp-btn {
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
gap: 0px;
|
|
47
|
+
height: 48px;
|
|
48
|
+
width: 80px;
|
|
49
|
+
min-width: 48px;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
border-radius: 0px;
|
|
53
|
+
border: none;
|
|
54
|
+
padding: 0px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.swp-toolbar-group .swp-btn span {
|
|
58
|
+
font-size: 12px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.swp-btn {
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
gap: 8px;
|
|
66
|
+
padding: 0px 12px;
|
|
67
|
+
border: 1px solid #dee2e6;
|
|
68
|
+
background: #ffffff;
|
|
69
|
+
border-radius: 6px;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
color: #495057;
|
|
73
|
+
transition: all 0.2s ease;
|
|
74
|
+
font-family: inherit;
|
|
75
|
+
height: 40px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.swp-btn:hover {
|
|
79
|
+
background: #e9ecef;
|
|
80
|
+
border-color: #adb5bd;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.swp-btn:active {
|
|
84
|
+
transform: scale(0.98);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.swp-btn-primary {
|
|
88
|
+
background: #007bff;
|
|
89
|
+
color: white;
|
|
90
|
+
border-color: #007bff;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.swp-btn-primary:hover {
|
|
94
|
+
background: #0056b3;
|
|
95
|
+
border-color: #0056b3;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.swp-btn-icon-only {
|
|
99
|
+
padding: 0px 12px;
|
|
100
|
+
justify-content: center;
|
|
101
|
+
align-items: center;
|
|
102
|
+
aspect-ratio: 1 / 1;
|
|
103
|
+
max-width: 40px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.swp-icon {
|
|
107
|
+
font-size: 18px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.swp-layout-container {
|
|
111
|
+
display: flex;
|
|
112
|
+
flex-grow: 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.swp-control-container {
|
|
116
|
+
min-width: 348px;
|
|
117
|
+
background: #f8f9fa;
|
|
118
|
+
padding: 8px 16px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.swp-control-container.hidden {
|
|
122
|
+
display: block;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Canvas Container */
|
|
126
|
+
.swp-canvas-container {
|
|
127
|
+
position: relative;
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
min-height: 400px;
|
|
132
|
+
padding: 8px;
|
|
133
|
+
border-top: 1px solid #dee2e6;
|
|
134
|
+
border-right: 1px solid #dee2e6;
|
|
135
|
+
border-top-right-radius: 8px;
|
|
136
|
+
flex-grow: 1;
|
|
137
|
+
min-width: 452px;;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.swp-canvas {
|
|
141
|
+
max-width: 100%;
|
|
142
|
+
height: auto;
|
|
143
|
+
background: white;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* Adjustments Panel */
|
|
147
|
+
.swp-adjustments-panel,
|
|
148
|
+
.swp-filters-panel,
|
|
149
|
+
.swp-resize-panel {
|
|
150
|
+
display: none;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.swp-adjustments-panel.active,
|
|
154
|
+
.swp-filters-panel.active,
|
|
155
|
+
.swp-resize-panel.active {
|
|
156
|
+
display: block;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.swp-adjustments-panel h3,
|
|
160
|
+
.swp-filters-panel h3,
|
|
161
|
+
.swp-resize-panel h3 {
|
|
162
|
+
margin: 0 0 15px 0;
|
|
163
|
+
font-size: 16px;
|
|
164
|
+
font-weight: 600;
|
|
165
|
+
color: #212529;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.swp-adjustment {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: 12px;
|
|
172
|
+
margin-bottom: 15px;
|
|
173
|
+
width: 100%;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.swp-adjustment label {
|
|
177
|
+
min-width: 100px;
|
|
178
|
+
font-size: 14px;
|
|
179
|
+
color: #495057;
|
|
180
|
+
font-weight: 500;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.swp-adjustment input[type="range"] {
|
|
184
|
+
flex: 1;
|
|
185
|
+
flex-shrink: 1;
|
|
186
|
+
height: 6px;
|
|
187
|
+
border-radius: 3px;
|
|
188
|
+
background: #e9ecef;
|
|
189
|
+
outline: none;
|
|
190
|
+
-webkit-appearance: none;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.swp-adjustment input[type="range"]::-webkit-slider-thumb {
|
|
194
|
+
-webkit-appearance: none;
|
|
195
|
+
appearance: none;
|
|
196
|
+
width: 18px;
|
|
197
|
+
height: 18px;
|
|
198
|
+
border-radius: 50%;
|
|
199
|
+
background: #007bff;
|
|
200
|
+
cursor: pointer;
|
|
201
|
+
transition: all 0.2s ease;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.swp-adjustment input[type="range"]::-webkit-slider-thumb:hover {
|
|
205
|
+
background: #0056b3;
|
|
206
|
+
transform: scale(1.1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.swp-adjustment input[type="range"]::-moz-range-thumb {
|
|
210
|
+
width: 18px;
|
|
211
|
+
height: 18px;
|
|
212
|
+
border-radius: 50%;
|
|
213
|
+
background: #007bff;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
border: none;
|
|
216
|
+
transition: all 0.2s ease;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.swp-adjustment input[type="range"]::-moz-range-thumb:hover {
|
|
220
|
+
background: #0056b3;
|
|
221
|
+
transform: scale(1.1);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.swp-value {
|
|
225
|
+
text-align: right;
|
|
226
|
+
font-size: 14px;
|
|
227
|
+
color: #6c757d;
|
|
228
|
+
font-weight: 500;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Resize Panel */
|
|
232
|
+
.swp-resize-controls {
|
|
233
|
+
display: flex;
|
|
234
|
+
flex-direction: column;
|
|
235
|
+
gap: 15px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.swp-resize-controls .swp-adjustment {
|
|
239
|
+
display: flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
gap: 10px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.swp-resize-controls input[type="number"] {
|
|
245
|
+
flex: 1;
|
|
246
|
+
padding: 8px 12px;
|
|
247
|
+
border: 1px solid #dee2e6;
|
|
248
|
+
border-radius: 6px;
|
|
249
|
+
font-size: 14px;
|
|
250
|
+
color: #495057;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.swp-resize-controls input[type="number"]:focus {
|
|
254
|
+
outline: none;
|
|
255
|
+
border-color: #007bff;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.swp-resize-controls input[type="checkbox"] {
|
|
259
|
+
width: 18px;
|
|
260
|
+
height: 18px;
|
|
261
|
+
cursor: pointer;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.swp-resize-controls label {
|
|
265
|
+
display: flex;
|
|
266
|
+
align-items: center;
|
|
267
|
+
gap: 8px;
|
|
268
|
+
cursor: pointer;
|
|
269
|
+
font-size: 14px;
|
|
270
|
+
color: #495057;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.swp-resize-controls button {
|
|
274
|
+
margin-top: 10px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
/* Filters Panel */
|
|
279
|
+
.swp-filters-grid {
|
|
280
|
+
display: grid;
|
|
281
|
+
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
|
282
|
+
gap: 15px;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.swp-filter-btn {
|
|
286
|
+
display: flex;
|
|
287
|
+
flex-direction: column;
|
|
288
|
+
align-items: center;
|
|
289
|
+
gap: 8px;
|
|
290
|
+
padding: 12px;
|
|
291
|
+
border: 2px solid #dee2e6;
|
|
292
|
+
background: #ffffff;
|
|
293
|
+
border-radius: 8px;
|
|
294
|
+
cursor: pointer;
|
|
295
|
+
font-size: 13px;
|
|
296
|
+
color: #495057;
|
|
297
|
+
transition: all 0.2s ease;
|
|
298
|
+
font-family: inherit;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.swp-filter-btn:hover {
|
|
302
|
+
border-color: #007bff;
|
|
303
|
+
background: #f8f9fa;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.swp-filter-btn.active {
|
|
307
|
+
border-color: #007bff;
|
|
308
|
+
background: #e7f3ff;
|
|
309
|
+
color: #007bff;
|
|
310
|
+
font-weight: 600;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.swp-filter-preview {
|
|
314
|
+
width: 60px;
|
|
315
|
+
height: 60px;
|
|
316
|
+
border-radius: 6px;
|
|
317
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
318
|
+
display: block;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.swp-filter-preview[data-filter="grayscale"] {
|
|
322
|
+
filter: grayscale(100%);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.swp-filter-preview[data-filter="sepia"] {
|
|
326
|
+
filter: sepia(100%);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.swp-filter-preview[data-filter="invert"] {
|
|
330
|
+
filter: invert(100%);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.swp-filter-preview[data-filter="blur"] {
|
|
334
|
+
filter: blur(3px);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.swp-filter-preview[data-filter="none"] {
|
|
338
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* Responsive Design */
|
|
342
|
+
@media (max-width: 768px) {
|
|
343
|
+
.swp-toolbar {
|
|
344
|
+
padding: 10px;
|
|
345
|
+
gap: 5px;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.swp-toolbar-group {
|
|
349
|
+
gap: 5px;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.swp-btn {
|
|
353
|
+
padding: 6px 12px;
|
|
354
|
+
font-size: 12px;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.swp-btn span:not(.swp-icon) {
|
|
358
|
+
display: none;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.swp-canvas-container {
|
|
362
|
+
min-height: 300px;
|
|
363
|
+
padding: 10px;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.swp-adjustments-panel,
|
|
367
|
+
.swp-filters-panel {
|
|
368
|
+
padding: 15px;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.swp-adjustment {
|
|
372
|
+
flex-wrap: wrap;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.swp-adjustment label {
|
|
376
|
+
min-width: 100%;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.swp-filters-grid {
|
|
380
|
+
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
|
381
|
+
gap: 10px;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.swp-filter-preview {
|
|
385
|
+
width: 50px;
|
|
386
|
+
height: 50px;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/* Loading State */
|
|
391
|
+
.swp-loading {
|
|
392
|
+
position: absolute;
|
|
393
|
+
top: 50%;
|
|
394
|
+
left: 50%;
|
|
395
|
+
transform: translate(-50%, -50%);
|
|
396
|
+
font-size: 14px;
|
|
397
|
+
color: #6c757d;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* Empty State */
|
|
401
|
+
.swp-empty-state {
|
|
402
|
+
text-align: center;
|
|
403
|
+
padding: 60px 20px;
|
|
404
|
+
color: #6c757d;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.swp-empty-state-icon {
|
|
408
|
+
font-size: 48px;
|
|
409
|
+
margin-bottom: 15px;
|
|
410
|
+
opacity: 0.5;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.swp-empty-state-text {
|
|
414
|
+
font-size: 16px;
|
|
415
|
+
margin-bottom: 20px;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* Animations */
|
|
419
|
+
@keyframes fadeIn {
|
|
420
|
+
from {
|
|
421
|
+
opacity: 0;
|
|
422
|
+
transform: translateY(-10px);
|
|
423
|
+
}
|
|
424
|
+
to {
|
|
425
|
+
opacity: 1;
|
|
426
|
+
transform: translateY(0);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.swp-adjustments-panel.active,
|
|
431
|
+
.swp-filters-panel.active {
|
|
432
|
+
animation: fadeIn 0.3s ease;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* Print Styles */
|
|
436
|
+
@media print {
|
|
437
|
+
.swp-toolbar,
|
|
438
|
+
.swp-adjustments-panel,
|
|
439
|
+
.swp-filters-panel {
|
|
440
|
+
display: none;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.swp-canvas-container {
|
|
444
|
+
padding: 0;
|
|
445
|
+
background: transparent;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
package/dist/swp.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SWP=t():e.SWP=t()}(this,()=>(()=>{"use strict";var e={d:(t,a)=>{for(var s in a)e.o(a,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:a[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{default:()=>s});class a{constructor(e,t={}){this.container=e,this.options={imageUrl:t.imageUrl||null,width:t.width||800,height:t.height||600,showIcons:void 0===t.showIcons||t.showIcons,showLabels:void 0===t.showLabels||t.showLabels,labels:{upload:void 0!==t.labels?.upload?t.labels.upload:"Upload",rotateLeft:void 0!==t.labels?.rotateLeft?t.labels.rotateLeft:null,rotateRight:void 0!==t.labels?.rotateRight?t.labels.rotateRight:null,flipH:void 0!==t.labels?.flipH?t.labels.flipH:null,flipV:void 0!==t.labels?.flipV?t.labels.flipV:null,resize:void 0!==t.labels?.resize?t.labels.resize:"Resize",adjust:void 0!==t.labels?.adjust?t.labels.adjust:"Adjust",filters:void 0!==t.labels?.filters?t.labels.filters:"Filters",reset:void 0!==t.labels?.reset?t.labels.reset:"Reset",save:void 0!==t.labels?.save?t.labels.save:"Save"}},this.canvas=null,this.ctx=null,this.originalImage=null,this.currentImage=null,this.history=[],this.currentState={brightness:100,contrast:100,saturation:100,rotation:0,flipH:!1,flipV:!1,filter:"none"},this.eventListeners={},this.init()}init(){this.createUI(),this.options.imageUrl&&this.loadImage(this.options.imageUrl)}createUI(){this.container.innerHTML="",this.container.classList.add("swp-container");const e=document.createElement("div");e.className="swp-wrapper";const t=document.createElement("div");t.className="swp-toolbar",t.innerHTML=this.createToolbarHTML();const a=document.createElement("div");a.className="swp-layout-container";const s=document.createElement("div");s.className="swp-control-container";const n=document.createElement("div");n.className="swp-canvas-container",this.canvas=document.createElement("canvas"),this.canvas.width=this.options.width,this.canvas.height=this.options.height,this.canvas.className="swp-canvas",this.ctx=this.canvas.getContext("2d"),n.appendChild(this.canvas);const i=document.createElement("div");i.className="swp-adjustments-panel",i.innerHTML=this.createAdjustmentsPanelHTML();const r=document.createElement("div");r.className="swp-filters-panel",r.innerHTML=this.createFiltersPanelHTML();const l=document.createElement("div");l.className="swp-resize-panel",l.innerHTML=this.createResizePanelHTML(),e.appendChild(t),e.appendChild(a),a.appendChild(n),a.appendChild(s),s.appendChild(i),s.appendChild(r),s.appendChild(l),this.container.appendChild(e),this.bindEvents()}createToolbarHTML(){const{showIcons:e,showLabels:t,labels:a}=this.options,s=(a,s,n,i)=>{const r=t&&null!==n?`<span>${n}</span>`:"";return`<button class="swp-btn${r?"":" swp-btn-icon-only"}" data-action="${a}" title="${i}">${e?`<span class="swp-icon"><i class="${s}"></i></span>`:""}${r}</button>`};return`\n <div class="swp-toolbar-group">\n ${s("upload","fas fa-folder",a.upload,"Upload Image")}\n <input type="file" id="swp-file-input" accept="image/*" style="display: none;">\n </div>\n \n <div class="swp-toolbar-group" style="margin: 0px auto;">\n ${s("rotate-left","fas fa-undo",a.rotateLeft,"Rotate Left")}\n ${s("rotate-right","fas fa-redo",a.rotateRight,"Rotate Right")}\n ${s("flip-h","fas fa-arrows-alt-h",a.flipH,"Flip Horizontal")}\n ${s("flip-v","fas fa-arrows-alt-v",a.flipV,"Flip Vertical")}\n </div>\n\n <div class="swp-toolbar-group">\n ${s("reset","fas fa-history",a.reset,"Reset")}\n </div>\n\n <div class="swp-toolbar-group">\n ${s("toggle-resize","fas fa-expand-arrows-alt",a.resize,"Resize")}\n ${s("toggle-adjustments","fas fa-sliders-h",a.adjust,"Adjustments")}\n ${s("toggle-filters","fas fa-magic",a.filters,"Filters")}\n </div>\n <div class="swp-toolbar-group">\n <button class="swp-btn swp-btn-primary${t&&null!==a.save?"":" swp-btn-icon-only"}" data-action="download" title="Download">\n ${e?'<span class="swp-icon"><i class="fas fa-save"></i></span>':""}\n ${t&&null!==a.save?`<span>${a.save}</span>`:""}\n </button>\n </div>\n `}createAdjustmentsPanelHTML(){return'\n <h3>Adjustments</h3>\n <div class="swp-adjustment">\n <label>Brightness</label>\n <input type="range" id="swp-brightness" min="0" max="200" value="100">\n <span class="swp-value">100%</span>\n </div>\n <div class="swp-adjustment">\n <label>Contrast</label>\n <input type="range" id="swp-contrast" min="0" max="200" value="100">\n <span class="swp-value">100%</span>\n </div>\n <div class="swp-adjustment">\n <label>Saturation</label>\n <input type="range" id="swp-saturation" min="0" max="200" value="100">\n <span class="swp-value">100%</span>\n </div>\n '}createResizePanelHTML(){return'\n <h3>Resize Image</h3>\n <div class="swp-resize-controls">\n <div class="swp-adjustment">\n <label>Width (px)</label>\n <input type="number" id="swp-resize-width" min="1" max="5000" value="800">\n </div>\n <div class="swp-adjustment">\n <label>Height (px)</label>\n <input type="number" id="swp-resize-height" min="1" max="5000" value="600">\n </div>\n <div class="swp-adjustment">\n <label>\n <input type="checkbox" id="swp-maintain-ratio" checked>\n Maintain aspect ratio\n </label>\n </div>\n <button class="swp-btn swp-btn-primary" data-action="apply-resize">Apply Resize</button>\n </div>\n '}createFiltersPanelHTML(){return`\n <h3>Filters</h3>\n <div class="swp-filters-grid">\n ${[{name:"none",label:"None"},{name:"grayscale",label:"Grayscale"},{name:"sepia",label:"Sepia"},{name:"invert",label:"Invert"},{name:"blur",label:"Blur"}].map(e=>`\n <button class="swp-filter-btn ${"none"===e.name?"active":""}" \n data-filter="${e.name}">\n <span class="swp-filter-preview" data-filter="${e.name}"></span>\n <span>${e.label}</span>\n </button>\n `).join("")}\n </div>\n `}bindEvents(){this.container.querySelectorAll("[data-action]").forEach(e=>{e.addEventListener("click",e=>{const t=e.currentTarget.getAttribute("data-action");this.handleAction(t)})});const e=this.container.querySelector("#swp-file-input");e&&e.addEventListener("change",e=>{const t=e.target.files[0];if(t){const e=new FileReader;e.onload=e=>{this.loadImage(e.target.result)},e.readAsDataURL(t)}}),["brightness","contrast","saturation"].forEach(e=>{const t=this.container.querySelector(`#swp-${e}`);t&&t.addEventListener("input",t=>{const a=parseInt(t.target.value);t.target.nextElementSibling.textContent=a+"%",this.setAdjustment(e,a)})}),this.container.querySelectorAll("[data-filter]").forEach(e=>{e.classList.contains("swp-filter-btn")&&e.addEventListener("click",e=>{const t=e.currentTarget.getAttribute("data-filter");this.applyFilter(t),this.container.querySelectorAll(".swp-filter-btn").forEach(e=>{e.classList.remove("active")}),e.currentTarget.classList.add("active")})})}bindResizeInputs(){const e=this.container.querySelector("#swp-resize-width"),t=this.container.querySelector("#swp-resize-height"),a=this.container.querySelector("#swp-maintain-ratio");if(!e||!t||!this.currentImage)return;const s=e.cloneNode(!0),n=t.cloneNode(!0);e.parentNode.replaceChild(s,e),t.parentNode.replaceChild(n,t);const i=this.currentImage.width/this.currentImage.height;s.addEventListener("input",e=>{const t=parseInt(e.target.value);if(a.checked){const e=Math.round(t/i);n.value=e}this.updateCanvasSize(parseInt(s.value),parseInt(n.value))}),n.addEventListener("input",e=>{const t=parseInt(e.target.value);if(a.checked){const e=Math.round(t*i);s.value=e}this.updateCanvasSize(parseInt(s.value),parseInt(n.value))})}updateCanvasSize(e,t){!this.currentImage||!e||!t||e<1||t<1||(this.canvas.width=e,this.canvas.height=t,this.drawImage())}handleAction(e){switch(e){case"upload":this.container.querySelector("#swp-file-input").click();break;case"rotate-left":this.rotate(-90);break;case"rotate-right":this.rotate(90);break;case"flip-h":this.flip("horizontal");break;case"flip-v":this.flip("vertical");break;case"toggle-adjustments":this.togglePanel(".swp-adjustments-panel");break;case"toggle-filters":this.togglePanel(".swp-filters-panel");break;case"toggle-resize":this.togglePanel(".swp-resize-panel");break;case"apply-resize":this.applyResize();break;case"reset":this.reset();break;case"download":this.download()}}togglePanel(e){const t=this.container.querySelector(e);t&&(t.classList.toggle("active"),[".swp-adjustments-panel",".swp-filters-panel",".swp-resize-panel"].forEach(t=>{t!==e&&this.container.querySelector(t)?.classList.remove("active")}))}loadImage(e){const t=new Image;t.crossOrigin="anonymous",t.onload=()=>{this.originalImage=t,this.currentImage=t,this.canvas.width=t.width,this.canvas.height=t.height;const e=this.container.querySelector("#swp-resize-width"),a=this.container.querySelector("#swp-resize-height");e&&(e.value=t.width),a&&(a.value=t.height),this.bindResizeInputs(),this.drawImage(),this.emit("load")},t.onerror=()=>{console.error("Failed to load image")},t.src=e}drawImage(){if(!this.currentImage)return;const e=this.canvas,t=this.ctx;t.clearRect(0,0,e.width,e.height),t.save(),t.translate(e.width/2,e.height/2),t.rotate(this.currentState.rotation*Math.PI/180),t.scale(this.currentState.flipH?-1:1,this.currentState.flipV?-1:1),t.filter=this.getFilterString(),t.drawImage(this.currentImage,-e.width/2,-e.height/2,e.width,e.height),t.restore(),this.emit("change")}getFilterString(){let e=[];switch(100!==this.currentState.brightness&&e.push(`brightness(${this.currentState.brightness}%)`),100!==this.currentState.contrast&&e.push(`contrast(${this.currentState.contrast}%)`),100!==this.currentState.saturation&&e.push(`saturate(${this.currentState.saturation}%)`),this.currentState.filter){case"grayscale":e.push("grayscale(100%)");break;case"sepia":e.push("sepia(100%)");break;case"invert":e.push("invert(100%)");break;case"blur":e.push("blur(5px)")}return e.length>0?e.join(" "):"none"}rotate(e){this.currentImage&&(this.currentState.rotation=(this.currentState.rotation+e)%360,this.drawImage())}flip(e){this.currentImage&&("horizontal"===e?this.currentState.flipH=!this.currentState.flipH:"vertical"===e&&(this.currentState.flipV=!this.currentState.flipV),this.drawImage())}setAdjustment(e,t){this.currentImage&&(this.currentState[e]=t,this.drawImage())}applyFilter(e){this.currentImage&&(this.currentState.filter=e,this.drawImage())}applyResize(){if(!this.currentImage)return;const e=this.container.querySelector("#swp-resize-width"),t=this.container.querySelector("#swp-resize-height"),a=parseInt(e.value),s=parseInt(t.value);if(!a||!s||a<1||s<1)return void alert("Please enter valid dimensions");const n=document.createElement("canvas");n.width=this.canvas.width,n.height=this.canvas.height,n.getContext("2d").drawImage(this.canvas,0,0);const i=new Image;i.onload=()=>{this.currentImage=i,this.originalImage=i,this.bindResizeInputs(),this.drawImage()},i.src=n.toDataURL()}crop(e,t,a,s){if(!this.currentImage)return;const n=document.createElement("canvas");n.width=a,n.height=s,n.getContext("2d").drawImage(this.canvas,e,t,a,s,0,0,a,s);const i=new Image;i.onload=()=>{this.currentImage=i,this.drawImage()},i.src=n.toDataURL()}reset(){this.currentState={brightness:100,contrast:100,saturation:100,rotation:0,flipH:!1,flipV:!1,filter:"none"},["brightness","contrast","saturation"].forEach(e=>{const t=this.container.querySelector(`#swp-${e}`);t&&(t.value=100,t.nextElementSibling.textContent="100%")}),this.container.querySelectorAll(".swp-filter-btn").forEach(e=>{e.classList.remove("active"),"none"===e.getAttribute("data-filter")&&e.classList.add("active")}),this.originalImage&&(this.currentImage=this.originalImage,this.drawImage())}getImageData(e="jpeg",t=.9){if(!this.canvas)return null;const a="png"===e?"image/png":"image/jpeg";return this.canvas.toDataURL(a,t)}download(){const e=this.getImageData("png");if(!e)return;const t=document.createElement("a");t.download=`swp-edited-${Date.now()}.png`,t.href=e,t.click(),this.emit("save")}on(e,t){this.eventListeners[e]||(this.eventListeners[e]=[]),this.eventListeners[e].push(t)}emit(e,t){this.eventListeners[e]&&this.eventListeners[e].forEach(e=>{e(t)})}}"undefined"!=typeof document&&document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("[data-swp]").forEach(e=>{const t={};if(e.dataset.swpImageUrl&&(t.imageUrl=e.dataset.swpImageUrl),e.dataset.swpWidth&&(t.width=parseInt(e.dataset.swpWidth)),e.dataset.swpHeight&&(t.height=parseInt(e.dataset.swpHeight)),void 0!==e.dataset.swpShowIcons&&(t.showIcons="false"!==e.dataset.swpShowIcons),void 0!==e.dataset.swpShowLabels&&(t.showLabels="false"!==e.dataset.swpShowLabels),e.dataset.swpLabels)try{let a=e.dataset.swpLabels.trim();a.startsWith("{")?t.labels=JSON.parse(a):(t.labels={},a.split(";").forEach(e=>{const[a,s]=e.split(":").map(e=>e.trim());if(a&&s){const e=s.replace(/^['"]|['"]$/g,"");t.labels[a]="null"===e?null:e}}))}catch(e){console.error("Failed to parse data-swp-labels:",e)}new a(e,t)})});const s=a;return"undefined"!=typeof window&&(window.SWP=a),t.default})());
|