senangwebs-photobooth 1.0.2 → 2.0.2

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 (43) hide show
  1. package/README.md +220 -236
  2. package/dist/swp.css +790 -256
  3. package/dist/swp.js +1 -1
  4. package/examples/data-attribute.html +69 -0
  5. package/examples/index.html +56 -51
  6. package/examples/studio.html +83 -0
  7. package/package.json +10 -6
  8. package/src/css/swp.css +790 -256
  9. package/src/js/core/Canvas.js +398 -0
  10. package/src/js/core/EventEmitter.js +188 -0
  11. package/src/js/core/History.js +250 -0
  12. package/src/js/core/Keyboard.js +323 -0
  13. package/src/js/filters/FilterManager.js +248 -0
  14. package/src/js/index.js +48 -0
  15. package/src/js/io/Clipboard.js +52 -0
  16. package/src/js/io/FileManager.js +150 -0
  17. package/src/js/layers/BlendModes.js +342 -0
  18. package/src/js/layers/Layer.js +415 -0
  19. package/src/js/layers/LayerManager.js +459 -0
  20. package/src/js/selection/Selection.js +167 -0
  21. package/src/js/swp.js +247 -761
  22. package/src/js/tools/BaseTool.js +264 -0
  23. package/src/js/tools/BrushTool.js +314 -0
  24. package/src/js/tools/CropTool.js +400 -0
  25. package/src/js/tools/EraserTool.js +155 -0
  26. package/src/js/tools/EyedropperTool.js +184 -0
  27. package/src/js/tools/FillTool.js +109 -0
  28. package/src/js/tools/GradientTool.js +141 -0
  29. package/src/js/tools/HandTool.js +51 -0
  30. package/src/js/tools/MarqueeTool.js +103 -0
  31. package/src/js/tools/MoveTool.js +465 -0
  32. package/src/js/tools/ShapeTool.js +285 -0
  33. package/src/js/tools/TextTool.js +253 -0
  34. package/src/js/tools/ToolManager.js +277 -0
  35. package/src/js/tools/ZoomTool.js +68 -0
  36. package/src/js/ui/ColorManager.js +71 -0
  37. package/src/js/ui/UI.js +1211 -0
  38. package/swp_preview1.png +0 -0
  39. package/swp_preview2.png +0 -0
  40. package/webpack.config.js +4 -11
  41. package/dist/styles.js +0 -1
  42. package/examples/customization.html +0 -360
  43. package/swp_preview.png +0 -0
package/dist/swp.css CHANGED
@@ -1,454 +1,988 @@
1
1
  /**
2
- * SenangWebs Photobooth (SWP) - Styles
3
- * @version 1.0.2
2
+ * SenangWebs Photobooth (SWP) - TOAST UI Style
3
+ * Simple & Clean Image Editor UI
4
+ * @version 3.0.0
4
5
  */
5
6
 
6
- /* Container */
7
- .swp-container {
8
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
9
- Ubuntu, Cantarell, sans-serif;
10
- max-width: 1200px;
7
+ /* CSS Variables */
8
+ :root {
9
+ --swp-bg-dark: #1e1e1e;
10
+ --swp-bg-medium: #2d2d2d;
11
+ --swp-bg-light: #3d3d3d;
12
+ --swp-bg-hover: #4a4a4a;
13
+ --swp-border: #404040;
14
+ --swp-border-light: #555555;
15
+ --swp-text: #ffffff;
16
+ --swp-text-secondary: #b0b0b0;
17
+ --swp-text-dim: #808080;
18
+ --swp-accent: #00FF99;
19
+ --swp-accent-hover: #33ffad;
20
+ --swp-accent-dim: rgba(0, 255, 153, 0.2);
21
+ --swp-accent-contrast: #000000;
22
+ --swp-success: #4ade80;
23
+ --swp-warning: #fbbf24;
24
+ --swp-error: #f87171;
25
+ --swp-canvas-bg: #151515;
26
+ --swp-header-height: 56px;
27
+ --swp-menu-height: 80px;
28
+ --swp-radius: 8px;
29
+ --swp-radius-sm: 6px;
30
+ --swp-radius-lg: 12px;
31
+ --swp-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
32
+ --swp-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.3);
33
+ --swp-transition: 0.2s ease;
34
+ }
35
+
36
+ /* Light Theme */
37
+ .swp-app.swp-theme-light {
38
+ --swp-bg-dark: #ffffff;
39
+ --swp-bg-medium: #f8f8f8;
40
+ --swp-bg-light: #ececec;
41
+ --swp-bg-hover: #e0e0e0;
42
+ --swp-border: #d4d4d4;
43
+ --swp-border-light: #c0c0c0;
44
+ --swp-text: #1a1a1a;
45
+ --swp-text-secondary: #666666;
46
+ --swp-text-dim: #999999;
47
+ --swp-accent: #2563eb;
48
+ --swp-accent-hover: #1d4ed8;
49
+ --swp-accent-dim: rgba(37, 99, 235, 0.15);
50
+ --swp-canvas-bg: #e8e8e8;
51
+ --swp-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
52
+ --swp-shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.1);
53
+ }
54
+
55
+ /* Reset */
56
+ .swp-app *, .swp-app *::before, .swp-app *::after {
11
57
  box-sizing: border-box;
58
+ margin: 0;
59
+ padding: 0;
12
60
  }
13
61
 
14
- .swp-wrapper {
15
- background: #ffffff;
16
- overflow: hidden;
17
- height: 100%;
62
+ /* Main Container */
63
+ .swp-app {
18
64
  display: flex;
19
65
  flex-direction: column;
66
+ width: 100%;
67
+ height: 100%;
68
+ min-height: 400px;
69
+ background: var(--swp-bg-dark);
70
+ color: var(--swp-text);
71
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
72
+ font-size: 14px;
73
+ overflow: hidden;
74
+ user-select: none;
75
+ -webkit-font-smoothing: antialiased;
20
76
  }
21
77
 
22
- /* Toolbar */
23
- .swp-toolbar {
78
+ /* ==================== HEADER ==================== */
79
+ .swp-header {
80
+ height: var(--swp-header-height);
81
+ background: var(--swp-bg-medium);
82
+ border-bottom: 1px solid var(--swp-border);
24
83
  display: flex;
25
- gap: 8px;
26
- padding: 8px;
27
- background: #f8f9fa;
28
- flex-wrap: wrap;
84
+ align-items: center;
29
85
  justify-content: space-between;
86
+ padding: 0 16px;
87
+ gap: 16px;
88
+ flex-shrink: 0;
30
89
  }
31
90
 
32
- .swp-toolbar-group {
91
+ .swp-header-left,
92
+ .swp-header-center,
93
+ .swp-header-right {
33
94
  display: flex;
34
- gap: 0px;
35
95
  align-items: center;
36
- border: 1px solid #dee2e6;
37
- border-radius: 8px;
38
- overflow: hidden;
96
+ gap: 8px;
39
97
  }
40
98
 
41
- .swp-toolbar-group .swp-btn {
42
- display: flex;
43
- flex-direction: column;
44
- gap: 0px;
45
- height: 48px;
46
- width: 80px;
47
- min-width: 48px;
48
- align-items: center;
99
+ .swp-header-center {
100
+ flex: 1;
49
101
  justify-content: center;
50
- border-radius: 0px;
51
- border: none;
52
- padding: 0px;
53
102
  }
54
103
 
55
- .swp-toolbar-group .swp-btn span {
56
- font-size: 12px;
104
+ .swp-header-btn {
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 8px;
108
+ padding: 10px 18px;
109
+ background: var(--swp-bg-light);
110
+ color: var(--swp-text);
111
+ border: 1px solid var(--swp-border);
112
+ border-radius: var(--swp-radius);
113
+ cursor: pointer;
114
+ font-size: 14px;
57
115
  font-weight: 500;
116
+ transition: all var(--swp-transition);
117
+ }
118
+
119
+ .swp-header-btn:hover {
120
+ background: var(--swp-accent);
121
+ border-color: var(--swp-accent);
122
+ color: var(--swp-accent-contrast);
58
123
  }
59
124
 
60
- .swp-toolbar-group .swp-btn .swp-icon {
125
+ .swp-header-btn ss-icon {
61
126
  font-size: 18px;
62
- padding: 2px;
63
- display: flex;
64
- align-items: center;
65
- justify-content: center;
66
127
  }
67
128
 
68
- .swp-btn {
129
+ /* Download Dropdown */
130
+ .swp-download-dropdown {
131
+ position: relative;
132
+ }
133
+
134
+ .swp-download-dropdown .swp-header-btn {
135
+ gap: 6px;
136
+ }
137
+
138
+ .swp-dropdown-arrow {
139
+ font-size: 14px !important;
140
+ opacity: 0.7;
141
+ margin-left: 2px;
142
+ }
143
+
144
+ .swp-dropdown-menu {
145
+ position: absolute;
146
+ top: 100%;
147
+ left: 0;
148
+ margin-top: 4px;
149
+ background: var(--swp-bg-medium);
150
+ border: 1px solid var(--swp-border);
151
+ border-radius: var(--swp-radius);
152
+ box-shadow: var(--swp-shadow);
153
+ min-width: 120px;
154
+ z-index: 200;
155
+ overflow: hidden;
156
+ animation: swp-dropdown-fade 0.15s ease;
157
+ }
158
+
159
+ @keyframes swp-dropdown-fade {
160
+ from {
161
+ opacity: 0;
162
+ transform: translateY(-4px);
163
+ }
164
+ to {
165
+ opacity: 1;
166
+ transform: translateY(0);
167
+ }
168
+ }
169
+
170
+ .swp-dropdown-menu[hidden] {
171
+ display: none;
172
+ }
173
+
174
+ .swp-dropdown-item {
175
+ display: block;
176
+ width: 100%;
177
+ padding: 10px 16px;
178
+ background: transparent;
179
+ color: var(--swp-text);
180
+ border: none;
181
+ font-size: 14px;
182
+ font-weight: 500;
183
+ text-align: left;
184
+ cursor: pointer;
185
+ transition: all var(--swp-transition);
186
+ }
187
+
188
+ .swp-dropdown-item:hover {
189
+ background: var(--swp-accent);
190
+ color: var(--swp-accent-contrast);
191
+ }
192
+
193
+ .swp-dropdown-item:not(:last-child) {
194
+ border-bottom: 1px solid var(--swp-border);
195
+ }
196
+
197
+ .swp-divider {
198
+ width: 1px;
199
+ height: 24px;
200
+ background: var(--swp-border);
201
+ margin: 0 8px;
202
+ }
203
+
204
+ /* Icon Button */
205
+ .swp-icon-btn {
206
+ width: 40px;
207
+ height: 40px;
69
208
  display: flex;
70
209
  align-items: center;
71
210
  justify-content: center;
72
- gap: 8px;
73
- padding: 0px 12px;
74
- border: 1px solid #dee2e6;
75
- background: #ffffff;
76
- border-radius: 6px;
211
+ background: transparent;
212
+ color: var(--swp-text-secondary);
213
+ border: none;
214
+ border-radius: var(--swp-radius);
77
215
  cursor: pointer;
78
- font-size: 14px;
79
- color: #495057;
80
- transition: all 0.2s ease;
81
- font-family: inherit;
82
- height: 40px;
216
+ transition: all var(--swp-transition);
83
217
  }
84
218
 
85
- .swp-btn:hover {
86
- background: #e9ecef;
87
- border-color: #adb5bd;
219
+ .swp-icon-btn:hover {
220
+ background: var(--swp-bg-hover);
221
+ color: var(--swp-text);
88
222
  }
89
223
 
90
- .swp-btn:active {
91
- transform: scale(0.98);
224
+ .swp-icon-btn:disabled {
225
+ opacity: 0.4;
226
+ cursor: not-allowed;
92
227
  }
93
228
 
94
- .swp-btn-primary {
95
- background: #007bff;
96
- color: white;
97
- border-color: #007bff;
229
+ .swp-icon-btn ss-icon {
230
+ font-size: 20px;
98
231
  }
99
232
 
100
- .swp-btn-primary:hover {
101
- background: #0056b3;
102
- border-color: #0056b3;
233
+ /* ==================== WORKSPACE ==================== */
234
+ .swp-workspace {
235
+ flex: 1;
236
+ background: var(--swp-canvas-bg);
237
+ background-image:
238
+ linear-gradient(45deg, #202020 25%, transparent 25%),
239
+ linear-gradient(-45deg, #202020 25%, transparent 25%),
240
+ linear-gradient(45deg, transparent 75%, #202020 75%),
241
+ linear-gradient(-45deg, transparent 75%, #202020 75%);
242
+ background-size: 20px 20px;
243
+ background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
244
+ overflow: hidden;
245
+ position: relative;
103
246
  }
104
247
 
105
- .swp-btn-icon-only {
106
- padding: 0px 12px;
107
- justify-content: center;
108
- align-items: center;
109
- aspect-ratio: 1 / 1;
110
- max-width: 40px;
248
+ .swp-theme-light .swp-workspace {
249
+ background-image:
250
+ linear-gradient(45deg, #d0d0d0 25%, transparent 25%),
251
+ linear-gradient(-45deg, #d0d0d0 25%, transparent 25%),
252
+ linear-gradient(45deg, transparent 75%, #d0d0d0 75%),
253
+ linear-gradient(-45deg, transparent 75%, #d0d0d0 75%);
111
254
  }
112
255
 
113
- .swp-icon {
114
- font-size: 18px;
256
+ /* Viewport */
257
+ .swp-viewport {
258
+ width: 100%;
259
+ height: 100%;
260
+ overflow: hidden;
261
+ position: relative;
115
262
  }
116
263
 
117
- .swp-layout-container {
118
- display: flex;
119
- flex-grow: 1;
264
+ .swp-canvas-wrapper {
265
+ position: relative;
266
+ box-shadow: var(--swp-shadow);
120
267
  }
121
268
 
122
- .swp-control-container {
123
- min-width: 348px;
124
- background: #f8f9fa;
125
- padding: 8px 16px;
269
+ .swp-display-canvas,
270
+ .swp-overlay-canvas {
271
+ position: absolute;
272
+ top: 0;
273
+ left: 0;
126
274
  }
127
275
 
128
- .swp-control-container.hidden {
129
- display: block;
276
+ .swp-overlay-canvas {
277
+ pointer-events: none;
130
278
  }
131
279
 
132
- /* Canvas Container */
133
- .swp-canvas-container {
134
- position: relative;
280
+ /* ==================== BOTTOM MENU BAR ==================== */
281
+ .swp-menu-bar {
282
+ height: var(--swp-menu-height);
283
+ background: var(--swp-bg-medium);
284
+ border-top: 1px solid var(--swp-border);
135
285
  display: flex;
136
286
  align-items: center;
137
287
  justify-content: center;
138
- min-height: 400px;
288
+ gap: 4px;
289
+ padding: 8px 16px;
290
+ flex-shrink: 0;
291
+ }
292
+
293
+ .swp-menu-item {
294
+ display: flex;
295
+ flex-direction: column;
296
+ align-items: center;
297
+ justify-content: center;
298
+ gap: 4px;
299
+ width: 72px;
300
+ height: 64px;
139
301
  padding: 8px;
140
- border-top: 1px solid #dee2e6;
141
- border-right: 1px solid #dee2e6;
142
- border-top-right-radius: 8px;
143
- flex-grow: 1;
144
- min-width: 452px;
302
+ background: transparent;
303
+ color: var(--swp-text-secondary);
304
+ border: none;
305
+ border-radius: var(--swp-radius);
306
+ cursor: pointer;
307
+ font-size: 12px;
308
+ font-weight: 500;
309
+ transition: all var(--swp-transition);
310
+ }
311
+
312
+ .swp-menu-item:hover {
313
+ background: var(--swp-bg-hover);
314
+ color: var(--swp-text);
315
+ }
316
+
317
+ .swp-menu-item.active {
318
+ background: var(--swp-accent);
319
+ color: var(--swp-accent-contrast);
145
320
  }
146
321
 
147
- .swp-canvas {
148
- max-width: 100%;
149
- height: auto;
150
- background: white;
322
+ .swp-menu-item ss-icon {
323
+ font-size: 24px;
151
324
  }
152
325
 
153
- /* Adjustments Panel */
154
- .swp-adjustments-panel,
155
- .swp-filters-panel,
156
- .swp-resize-panel {
326
+ /* ==================== SUBMENU ==================== */
327
+ .swp-submenu {
328
+ position: absolute;
329
+ bottom: calc(var(--swp-menu-height) + 16px);
330
+ left: 50%;
331
+ transform: translateX(-50%);
332
+ background: var(--swp-bg-medium);
333
+ border: 1px solid var(--swp-border);
334
+ border-radius: var(--swp-radius-lg);
335
+ box-shadow: var(--swp-shadow);
336
+ z-index: 100;
337
+ animation: swp-fade-up 0.2s ease;
338
+ }
339
+
340
+ @keyframes swp-fade-up {
341
+ from {
342
+ opacity: 0;
343
+ transform: translateX(-50%) translateY(10px);
344
+ }
345
+ to {
346
+ opacity: 1;
347
+ transform: translateX(-50%) translateY(0);
348
+ }
349
+ }
350
+
351
+ .swp-submenu[hidden] {
157
352
  display: none;
158
353
  }
159
354
 
160
- .swp-adjustments-panel.active,
161
- .swp-filters-panel.active,
162
- .swp-resize-panel.active {
163
- display: block;
355
+ .swp-submenu-content {
356
+ padding: 20px 24px;
357
+ min-width: 280px;
358
+ }
359
+
360
+ .swp-submenu-content.swp-submenu-wide {
361
+ min-width: 360px;
164
362
  }
165
363
 
166
- .swp-adjustments-panel h3,
167
- .swp-filters-panel h3,
168
- .swp-resize-panel h3 {
169
- margin: 0 0 15px 0;
364
+ .swp-submenu-title {
170
365
  font-size: 16px;
171
366
  font-weight: 600;
172
- color: #212529;
367
+ margin-bottom: 16px;
368
+ padding-bottom: 12px;
369
+ border-bottom: 1px solid var(--swp-border);
370
+ color: var(--swp-text);
371
+ }
372
+
373
+ .swp-submenu-group {
374
+ margin-bottom: 16px;
173
375
  }
174
376
 
175
- .swp-adjustment {
377
+ .swp-submenu-group:last-child {
378
+ margin-bottom: 0;
379
+ }
380
+
381
+ .swp-submenu-label {
382
+ display: block;
383
+ font-size: 12px;
384
+ font-weight: 500;
385
+ color: var(--swp-text-secondary);
386
+ text-transform: uppercase;
387
+ letter-spacing: 0.5px;
388
+ margin-bottom: 8px;
389
+ }
390
+
391
+ /* Button Group */
392
+ .swp-btn-group {
176
393
  display: flex;
177
- align-items: center;
178
- gap: 12px;
179
- margin-bottom: 15px;
180
- width: 100%;
394
+ gap: 6px;
181
395
  }
182
396
 
183
- .swp-adjustment label {
184
- min-width: 100px;
185
- font-size: 14px;
186
- color: #495057;
397
+ .swp-btn-group-lg .swp-submenu-btn {
398
+ flex: 1;
399
+ padding: 12px 16px;
400
+ }
401
+
402
+ .swp-submenu-btn {
403
+ display: flex;
404
+ align-items: center;
405
+ justify-content: center;
406
+ gap: 6px;
407
+ padding: 10px 14px;
408
+ background: var(--swp-bg-light);
409
+ color: var(--swp-text-secondary);
410
+ border: 1px solid var(--swp-border);
411
+ border-radius: var(--swp-radius-sm);
412
+ cursor: pointer;
413
+ font-size: 13px;
187
414
  font-weight: 500;
415
+ transition: all var(--swp-transition);
188
416
  }
189
417
 
190
- .swp-adjustment input[type="range"] {
418
+ .swp-submenu-btn:hover {
419
+ background: var(--swp-bg-hover);
420
+ color: var(--swp-text);
421
+ border-color: var(--swp-border-light);
422
+ }
423
+
424
+ .swp-submenu-btn.active {
425
+ background: var(--swp-accent);
426
+ color: var(--swp-accent-contrast);
427
+ border-color: var(--swp-accent);
428
+ }
429
+
430
+ .swp-submenu-btn ss-icon {
431
+ font-size: 18px;
432
+ }
433
+
434
+ /* Range Slider */
435
+ .swp-range-wrap {
436
+ display: flex;
437
+ align-items: center;
438
+ gap: 12px;
439
+ }
440
+
441
+ .swp-slider {
191
442
  flex: 1;
192
- flex-shrink: 1;
443
+ -webkit-appearance: none;
444
+ appearance: none;
193
445
  height: 6px;
446
+ background: var(--swp-bg-dark);
194
447
  border-radius: 3px;
195
- background: #e9ecef;
196
448
  outline: none;
197
- -webkit-appearance: none;
198
449
  }
199
450
 
200
- .swp-adjustment input[type="range"]::-webkit-slider-thumb {
451
+ .swp-slider::-webkit-slider-thumb {
201
452
  -webkit-appearance: none;
202
453
  appearance: none;
203
454
  width: 18px;
204
455
  height: 18px;
456
+ background: var(--swp-accent);
205
457
  border-radius: 50%;
206
- background: #007bff;
207
458
  cursor: pointer;
208
- transition: all 0.2s ease;
459
+ transition: all var(--swp-transition);
460
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
209
461
  }
210
462
 
211
- .swp-adjustment input[type="range"]::-webkit-slider-thumb:hover {
212
- background: #0056b3;
213
- transform: scale(1.1);
463
+ .swp-slider::-webkit-slider-thumb:hover {
464
+ transform: scale(1.15);
465
+ background: var(--swp-accent-hover);
214
466
  }
215
467
 
216
- .swp-adjustment input[type="range"]::-moz-range-thumb {
468
+ .swp-slider::-moz-range-thumb {
217
469
  width: 18px;
218
470
  height: 18px;
471
+ background: var(--swp-accent);
219
472
  border-radius: 50%;
220
- background: #007bff;
221
473
  cursor: pointer;
222
474
  border: none;
223
- transition: all 0.2s ease;
224
475
  }
225
476
 
226
- .swp-adjustment input[type="range"]::-moz-range-thumb:hover {
227
- background: #0056b3;
228
- transform: scale(1.1);
477
+ .swp-range-value {
478
+ min-width: 48px;
479
+ font-size: 13px;
480
+ color: var(--swp-text);
481
+ text-align: right;
482
+ font-weight: 500;
229
483
  }
230
484
 
231
- .swp-value {
232
- text-align: right;
485
+ /* Color Input */
486
+ .swp-color-input {
487
+ width: 100%;
488
+ height: 40px;
489
+ padding: 4px;
490
+ background: var(--swp-bg-dark);
491
+ border: 1px solid var(--swp-border);
492
+ border-radius: var(--swp-radius-sm);
493
+ cursor: pointer;
494
+ }
495
+
496
+ .swp-color-input::-webkit-color-swatch-wrapper {
497
+ padding: 0;
498
+ }
499
+
500
+ .swp-color-input::-webkit-color-swatch {
501
+ border: none;
502
+ border-radius: 4px;
503
+ }
504
+
505
+ /* Select */
506
+ .swp-select {
507
+ width: 100%;
508
+ padding: 10px 12px;
509
+ background: var(--swp-bg-dark);
510
+ color: var(--swp-text);
511
+ border: 1px solid var(--swp-border);
512
+ border-radius: var(--swp-radius-sm);
233
513
  font-size: 14px;
234
- color: #6c757d;
235
- font-weight: 500;
514
+ cursor: pointer;
515
+ outline: none;
516
+ transition: all var(--swp-transition);
236
517
  }
237
518
 
238
- /* Resize Panel */
239
- .swp-resize-controls {
240
- display: flex;
241
- flex-direction: column;
242
- gap: 15px;
519
+ .swp-select:focus {
520
+ border-color: var(--swp-accent);
521
+ box-shadow: 0 0 0 3px var(--swp-accent-dim);
522
+ }
523
+
524
+ /* Input Field */
525
+ .swp-input {
526
+ width: 100%;
527
+ padding: 10px 12px;
528
+ background: var(--swp-bg-dark);
529
+ color: var(--swp-text);
530
+ border: 1px solid var(--swp-border);
531
+ border-radius: var(--swp-radius-sm);
532
+ font-size: 14px;
533
+ outline: none;
534
+ transition: all var(--swp-transition);
535
+ }
536
+
537
+ .swp-input:focus {
538
+ border-color: var(--swp-accent);
539
+ box-shadow: 0 0 0 3px var(--swp-accent-dim);
243
540
  }
244
541
 
245
- .swp-resize-controls .swp-adjustment {
542
+ /* Resize Inputs */
543
+ .swp-resize-inputs {
246
544
  display: flex;
247
- align-items: center;
248
- gap: 10px;
545
+ gap: 12px;
249
546
  }
250
547
 
251
- .swp-resize-controls input[type="number"] {
548
+ .swp-input-group {
252
549
  flex: 1;
253
- padding: 8px 12px;
254
- border: 1px solid #dee2e6;
255
- border-radius: 6px;
256
- font-size: 14px;
257
- color: #495057;
258
550
  }
259
551
 
260
- .swp-resize-controls input[type="number"]:focus {
261
- outline: none;
262
- border-color: #007bff;
552
+ .swp-input-group label {
553
+ display: block;
554
+ font-size: 12px;
555
+ color: var(--swp-text-secondary);
556
+ margin-bottom: 6px;
263
557
  }
264
558
 
265
- .swp-resize-controls input[type="checkbox"] {
559
+ /* Checkbox */
560
+ .swp-checkbox-label {
561
+ display: flex;
562
+ align-items: center;
563
+ gap: 8px;
564
+ font-size: 14px;
565
+ color: var(--swp-text);
566
+ cursor: pointer;
567
+ }
568
+
569
+ .swp-checkbox-label input[type="checkbox"] {
266
570
  width: 18px;
267
571
  height: 18px;
572
+ accent-color: var(--swp-accent);
268
573
  cursor: pointer;
269
574
  }
270
575
 
271
- .swp-resize-controls label {
576
+ /* Button Group Wrap */
577
+ .swp-btn-group-wrap {
578
+ flex-wrap: wrap;
579
+ gap: 6px;
580
+ }
581
+
582
+ .swp-preset-btn {
583
+ font-size: 12px !important;
584
+ padding: 8px 12px !important;
585
+ }
586
+
587
+ /* Submenu Actions */
588
+ .swp-submenu-actions {
272
589
  display: flex;
273
- align-items: center;
274
590
  gap: 8px;
591
+ margin-top: 20px;
592
+ padding-top: 16px;
593
+ border-top: 1px solid var(--swp-border);
594
+ }
595
+
596
+ .swp-submenu-actions .swp-btn {
597
+ flex: 1;
598
+ }
599
+
600
+ /* Buttons */
601
+ .swp-btn {
602
+ padding: 10px 20px;
603
+ background: var(--swp-bg-light);
604
+ color: var(--swp-text);
605
+ border: 1px solid var(--swp-border);
606
+ border-radius: var(--swp-radius);
275
607
  cursor: pointer;
276
608
  font-size: 14px;
277
- color: #495057;
609
+ font-weight: 500;
610
+ transition: all var(--swp-transition);
611
+ }
612
+
613
+ .swp-btn:hover {
614
+ background: var(--swp-bg-hover);
615
+ border-color: var(--swp-border-light);
616
+ }
617
+
618
+ .swp-btn-primary {
619
+ background: var(--swp-accent);
620
+ color: var(--swp-accent-contrast);
621
+ border-color: var(--swp-accent);
278
622
  }
279
623
 
280
- .swp-resize-controls button {
281
- margin-top: 10px;
624
+ .swp-btn-primary:hover {
625
+ background: var(--swp-accent-hover);
626
+ border-color: var(--swp-accent-hover);
282
627
  }
283
628
 
284
- /* Filters Panel */
285
- .swp-filters-grid {
629
+ /* ==================== FILTER GRID ==================== */
630
+ .swp-filter-grid {
286
631
  display: grid;
287
- grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
288
- gap: 15px;
632
+ grid-template-columns: repeat(4, 1fr);
633
+ gap: 8px;
289
634
  }
290
635
 
291
636
  .swp-filter-btn {
292
637
  display: flex;
293
638
  flex-direction: column;
294
639
  align-items: center;
295
- gap: 8px;
296
- padding: 12px;
297
- border: 2px solid #dee2e6;
298
- background: #ffffff;
299
- border-radius: 8px;
640
+ gap: 6px;
641
+ padding: 8px;
642
+ background: var(--swp-bg-light);
643
+ border: 2px solid transparent;
644
+ border-radius: var(--swp-radius-sm);
300
645
  cursor: pointer;
301
- font-size: 13px;
302
- color: #495057;
303
- transition: all 0.2s ease;
304
- font-family: inherit;
646
+ font-size: 11px;
647
+ color: var(--swp-text-secondary);
648
+ transition: all var(--swp-transition);
305
649
  }
306
650
 
307
651
  .swp-filter-btn:hover {
308
- border-color: #007bff;
309
- background: #f8f9fa;
652
+ border-color: var(--swp-border-light);
653
+ color: var(--swp-text);
310
654
  }
311
655
 
312
656
  .swp-filter-btn.active {
313
- border-color: #007bff;
314
- background: #e7f3ff;
315
- color: #007bff;
316
- font-weight: 600;
657
+ border-color: var(--swp-accent);
658
+ color: var(--swp-text);
659
+ background: var(--swp-accent-dim);
317
660
  }
318
661
 
319
662
  .swp-filter-preview {
320
- width: 60px;
321
- height: 60px;
322
- border-radius: 6px;
323
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
324
- display: block;
663
+ width: 48px;
664
+ height: 48px;
665
+ background: linear-gradient(135deg, #ff6b6b, #4ecdc4, #45b7d1, #96c93d);
666
+ border-radius: 4px;
325
667
  }
326
668
 
327
- .swp-filter-preview[data-filter="grayscale"] {
669
+ .swp-filter-grayscale .swp-filter-preview,
670
+ .swp-filter-btn[data-filter="grayscale"] .swp-filter-preview {
328
671
  filter: grayscale(100%);
329
672
  }
330
673
 
331
- .swp-filter-preview[data-filter="sepia"] {
674
+ .swp-filter-sepia .swp-filter-preview,
675
+ .swp-filter-btn[data-filter="sepia"] .swp-filter-preview {
332
676
  filter: sepia(100%);
333
677
  }
334
678
 
335
- .swp-filter-preview[data-filter="invert"] {
679
+ .swp-filter-invert .swp-filter-preview,
680
+ .swp-filter-btn[data-filter="invert"] .swp-filter-preview {
336
681
  filter: invert(100%);
337
682
  }
338
683
 
339
- .swp-filter-preview[data-filter="blur"] {
340
- filter: blur(3px);
684
+ .swp-filter-blur .swp-filter-preview,
685
+ .swp-filter-btn[data-filter="blur"] .swp-filter-preview {
686
+ filter: blur(2px);
687
+ }
688
+
689
+ .swp-filter-brightness .swp-filter-preview,
690
+ .swp-filter-btn[data-filter="brightness"] .swp-filter-preview {
691
+ filter: brightness(130%);
692
+ }
693
+
694
+ .swp-filter-contrast .swp-filter-preview,
695
+ .swp-filter-btn[data-filter="contrast"] .swp-filter-preview {
696
+ filter: contrast(150%);
697
+ }
698
+
699
+ .swp-filter-sharpen .swp-filter-preview,
700
+ .swp-filter-btn[data-filter="sharpen"] .swp-filter-preview {
701
+ filter: contrast(120%) saturate(110%);
702
+ }
703
+
704
+ /* ==================== TEXT INPUT ==================== */
705
+ .swp-text-input {
706
+ position: absolute;
707
+ opacity: 0;
708
+ pointer-events: none;
709
+ }
710
+
711
+ /* ==================== SCROLLBAR ==================== */
712
+ .swp-app ::-webkit-scrollbar {
713
+ width: 8px;
714
+ height: 8px;
715
+ }
716
+
717
+ .swp-app ::-webkit-scrollbar-track {
718
+ background: transparent;
719
+ }
720
+
721
+ .swp-app ::-webkit-scrollbar-thumb {
722
+ background: var(--swp-border);
723
+ border-radius: 4px;
341
724
  }
342
725
 
343
- .swp-filter-preview[data-filter="none"] {
344
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
726
+ .swp-app ::-webkit-scrollbar-thumb:hover {
727
+ background: var(--swp-border-light);
345
728
  }
346
729
 
347
- /* Responsive Design */
730
+ /* ==================== RESPONSIVE ==================== */
348
731
  @media (max-width: 768px) {
349
- .swp-toolbar {
350
- padding: 10px;
351
- gap: 5px;
732
+ .swp-header {
733
+ padding: 0 12px;
352
734
  }
353
735
 
354
- .swp-toolbar-group {
355
- gap: 5px;
736
+ .swp-header-btn span {
737
+ display: none;
356
738
  }
357
739
 
358
- .swp-btn {
359
- padding: 6px 12px;
360
- font-size: 12px;
740
+ .swp-header-btn {
741
+ padding: 10px 12px;
361
742
  }
362
743
 
363
- .swp-btn span:not(.swp-icon) {
364
- display: none;
744
+ .swp-menu-item {
745
+ width: 56px;
746
+ height: 56px;
747
+ padding: 6px;
748
+ font-size: 10px;
749
+ }
750
+
751
+ .swp-menu-item ss-icon {
752
+ font-size: 20px;
753
+ }
754
+
755
+ .swp-menu-bar {
756
+ height: 72px;
757
+ gap: 2px;
758
+ padding: 8px;
759
+ }
760
+
761
+ .swp-submenu-content {
762
+ min-width: 260px;
763
+ padding: 16px;
365
764
  }
366
765
 
367
- .swp-canvas-container {
368
- min-height: 300px;
369
- padding: 10px;
766
+ .swp-submenu-content.swp-submenu-wide {
767
+ min-width: 300px;
370
768
  }
371
769
 
372
- .swp-adjustments-panel,
373
- .swp-filters-panel {
374
- padding: 15px;
770
+ .swp-filter-grid {
771
+ grid-template-columns: repeat(3, 1fr);
375
772
  }
773
+ }
376
774
 
377
- .swp-adjustment {
378
- flex-wrap: wrap;
775
+ @media (max-width: 480px) {
776
+ .swp-header-left .swp-header-btn:nth-child(2) {
777
+ display: none;
379
778
  }
380
779
 
381
- .swp-adjustment label {
382
- min-width: 100%;
780
+ .swp-menu-item {
781
+ width: 48px;
782
+ height: 52px;
383
783
  }
384
784
 
385
- .swp-filters-grid {
386
- grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
387
- gap: 10px;
785
+ .swp-menu-item span {
786
+ display: none;
388
787
  }
389
788
 
390
- .swp-filter-preview {
391
- width: 50px;
392
- height: 50px;
789
+ .swp-submenu {
790
+ left: 8px;
791
+ right: 8px;
792
+ transform: none;
793
+ }
794
+
795
+ .swp-submenu-content,
796
+ .swp-submenu-content.swp-submenu-wide {
797
+ min-width: auto;
798
+ }
799
+
800
+ .swp-filter-grid {
801
+ grid-template-columns: repeat(2, 1fr);
393
802
  }
394
803
  }
395
804
 
396
- /* Loading State */
397
- .swp-loading {
805
+ /* ==================== SIDE PANEL ==================== */
806
+ .swp-side-panel {
398
807
  position: absolute;
399
- top: 50%;
400
- left: 50%;
401
- transform: translate(-50%, -50%);
808
+ top: var(--swp-header-height);
809
+ right: 0;
810
+ width: 280px;
811
+ bottom: var(--swp-menu-height);
812
+ background: var(--swp-bg-medium);
813
+ border-left: 1px solid var(--swp-border);
814
+ display: flex;
815
+ flex-direction: column;
816
+ z-index: 50;
817
+ animation: swp-slide-in 0.2s ease;
818
+ }
819
+
820
+ @keyframes swp-slide-in {
821
+ from {
822
+ transform: translateX(100%);
823
+ opacity: 0;
824
+ }
825
+ to {
826
+ transform: translateX(0);
827
+ opacity: 1;
828
+ }
829
+ }
830
+
831
+ .swp-side-panel[hidden] {
832
+ display: none;
833
+ }
834
+
835
+ .swp-side-panel-header {
836
+ display: flex;
837
+ align-items: center;
838
+ justify-content: space-between;
839
+ padding: 12px 16px;
840
+ background: var(--swp-bg-light);
841
+ border-bottom: 1px solid var(--swp-border);
842
+ }
843
+
844
+ .swp-side-panel-title {
402
845
  font-size: 14px;
403
- color: #6c757d;
846
+ font-weight: 600;
847
+ color: var(--swp-text);
848
+ }
849
+
850
+ .swp-side-panel-close {
851
+ width: 28px;
852
+ height: 28px;
853
+ }
854
+
855
+ .swp-side-panel-content {
856
+ flex: 1;
857
+ overflow-y: auto;
858
+ padding: 12px;
404
859
  }
405
860
 
406
- /* Empty State */
407
- .swp-empty-state {
861
+ .swp-panel-list {
862
+ display: flex;
863
+ flex-direction: column;
864
+ gap: 4px;
865
+ }
866
+
867
+ .swp-panel-empty {
408
868
  text-align: center;
409
- padding: 60px 20px;
410
- color: #6c757d;
869
+ color: var(--swp-text-dim);
870
+ padding: 24px;
871
+ font-size: 13px;
872
+ }
873
+
874
+ .swp-panel-item {
875
+ display: flex;
876
+ align-items: center;
877
+ gap: 10px;
878
+ padding: 10px 12px;
879
+ background: var(--swp-bg-dark);
880
+ border-radius: var(--swp-radius);
881
+ cursor: pointer;
882
+ transition: all var(--swp-transition);
883
+ border: 1px solid transparent;
884
+ font-size: 13px;
885
+ color: var(--swp-text-secondary);
411
886
  }
412
887
 
413
- .swp-empty-state-icon {
414
- font-size: 48px;
415
- margin-bottom: 15px;
416
- opacity: 0.5;
888
+ .swp-panel-item:hover {
889
+ background: var(--swp-bg-hover);
890
+ color: var(--swp-text);
417
891
  }
418
892
 
419
- .swp-empty-state-text {
893
+ .swp-panel-item.active {
894
+ background: var(--swp-accent-dim);
895
+ border-color: var(--swp-accent);
896
+ color: var(--swp-text);
897
+ }
898
+
899
+ .swp-panel-item ss-icon {
420
900
  font-size: 16px;
421
- margin-bottom: 20px;
901
+ opacity: 0.7;
422
902
  }
423
903
 
424
- /* Animations */
425
- @keyframes fadeIn {
426
- from {
427
- opacity: 0;
428
- transform: translateY(-10px);
429
- }
430
- to {
431
- opacity: 1;
432
- transform: translateY(0);
433
- }
904
+ .swp-panel-item span {
905
+ flex: 1;
906
+ overflow: hidden;
907
+ text-overflow: ellipsis;
908
+ white-space: nowrap;
909
+ }
910
+
911
+ /* Layer visibility button */
912
+ .swp-layer-vis-btn {
913
+ width: 24px;
914
+ height: 24px;
915
+ border: none;
916
+ background: transparent;
917
+ cursor: pointer;
918
+ color: var(--swp-text-dim);
919
+ display: flex;
920
+ align-items: center;
921
+ justify-content: center;
922
+ border-radius: var(--swp-radius-sm);
923
+ transition: all var(--swp-transition);
434
924
  }
435
925
 
436
- .swp-adjustments-panel.active,
437
- .swp-filters-panel.active {
438
- animation: fadeIn 0.3s ease;
926
+ .swp-layer-vis-btn:hover {
927
+ background: var(--swp-bg-light);
439
928
  }
440
929
 
441
- /* Print Styles */
442
- @media print {
443
- .swp-toolbar,
444
- .swp-adjustments-panel,
445
- .swp-filters-panel {
446
- display: none;
447
- }
930
+ .swp-layer-vis-btn.visible {
931
+ color: var(--swp-accent);
932
+ }
448
933
 
449
- .swp-canvas-container {
450
- padding: 0;
451
- background: transparent;
452
- }
934
+ .swp-layer-name {
935
+ flex: 1;
936
+ overflow: hidden;
937
+ text-overflow: ellipsis;
938
+ white-space: nowrap;
939
+ }
940
+
941
+ .swp-layer-opacity {
942
+ font-size: 11px;
943
+ color: var(--swp-text-dim);
944
+ background: var(--swp-bg-light);
945
+ padding: 2px 6px;
946
+ border-radius: 10px;
947
+ }
948
+
949
+ /* Panel Actions */
950
+ .swp-panel-actions {
951
+ display: flex;
952
+ gap: 8px;
953
+ padding: 8px;
954
+ border-top: 1px solid var(--swp-border);
955
+ background: var(--swp-bg-light);
956
+ justify-content: space-between;
957
+ margin-top: 12px;
958
+ border-radius: 10px;
959
+ }
960
+
961
+ .swp-btn-sm {
962
+ padding: 8px 12px;
963
+ font-size: 12px;
964
+ display: flex;
965
+ align-items: center;
966
+ gap: 6px;
967
+ }
968
+
969
+ .swp-btn-sm ss-icon {
970
+ font-size: 14px;
971
+ }
972
+
973
+ .swp-btn-danger {
974
+ color: var(--swp-error);
975
+ }
976
+
977
+ .swp-btn-danger:hover {
978
+ background: var(--swp-error);
979
+ color: white;
980
+ border-color: var(--swp-error);
981
+ }
982
+
983
+ /* Active state for header icon buttons */
984
+ .swp-icon-btn.active {
985
+ background: var(--swp-accent);
986
+ color: var(--swp-accent-contrast);
453
987
  }
454
988