@bugspotter/sdk 0.2.4-alpha.5 → 0.3.0

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.
@@ -9,6 +9,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.StyleManager = void 0;
10
10
  class StyleManager {
11
11
  constructor(config = {}) {
12
+ // ============================================================================
13
+ // SPACING & SIZING CONSTANTS
14
+ // ============================================================================
15
+ this.SPACING = {
16
+ xs: 8,
17
+ sm: 12,
18
+ md: 16,
19
+ lg: 20,
20
+ };
21
+ this.BREAKPOINTS = {
22
+ tablet: 768,
23
+ mobile: 480,
24
+ };
25
+ this.MODAL_SIZES = {
26
+ desktop: '600px',
27
+ tablet: '500px',
28
+ mobilePercent: '98%',
29
+ headerHeight: '30px',
30
+ };
31
+ // ============================================================================
32
+ // FONT & LAYOUT CONSTANTS
33
+ // ============================================================================
34
+ this.FONT_SIZES = {
35
+ h2: '20px',
36
+ h2Mobile: '18px',
37
+ label: '14px',
38
+ labelMobile: '13px',
39
+ body: '14px',
40
+ small: '12px',
41
+ sr: '13px',
42
+ };
43
+ this.BORDER_STYLES = {
44
+ primary: '1px solid #e0e0e0',
45
+ light: '1px solid #ddd',
46
+ };
47
+ this.SHADOW_STYLES = {
48
+ modal: '0 4px 6px rgba(0, 0, 0, 0.1)',
49
+ };
12
50
  this.config = {
13
51
  primaryColor: config.primaryColor || '#007bff',
14
52
  dangerColor: config.dangerColor || '#dc3545',
@@ -22,6 +60,24 @@ class StyleManager {
22
60
  */
23
61
  generateStyles() {
24
62
  return `
63
+ ${this.generateOverlayStyles()}
64
+ ${this.generateModalStyles()}
65
+ ${this.generateHeaderStyles()}
66
+ ${this.generateBodyStyles()}
67
+ ${this.generateFormStyles()}
68
+ ${this.generateButtonStyles()}
69
+ ${this.generatePIIStyles()}
70
+ ${this.generateLoadingStyles()}
71
+ ${this.generateAccessibilityStyles()}
72
+ ${this.generateTabletResponsiveStyles()}
73
+ ${this.generateMobileResponsiveStyles()}
74
+ `;
75
+ }
76
+ // ============================================================================
77
+ // COMPONENT STYLES - OVERLAY & MODAL
78
+ // ============================================================================
79
+ generateOverlayStyles() {
80
+ return `
25
81
  .overlay {
26
82
  position: fixed;
27
83
  top: 0;
@@ -35,20 +91,35 @@ class StyleManager {
35
91
  z-index: ${this.config.zIndex};
36
92
  font-family: ${this.config.fontFamily};
37
93
  }
38
-
94
+ `;
95
+ }
96
+ generateModalStyles() {
97
+ return `
39
98
  .modal {
40
99
  background: white;
41
100
  border-radius: 8px;
42
101
  width: 90%;
43
- max-width: 600px;
102
+ max-width: ${this.MODAL_SIZES.desktop};
44
103
  max-height: 90vh;
45
104
  overflow-y: auto;
46
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
105
+ box-shadow: ${this.SHADOW_STYLES.modal};
106
+ scrollbar-width: none;
107
+ -ms-overflow-style: none;
47
108
  }
48
109
 
110
+ .modal::-webkit-scrollbar {
111
+ display: none;
112
+ }
113
+ `;
114
+ }
115
+ // ============================================================================
116
+ // COMPONENT STYLES - HEADER
117
+ // ============================================================================
118
+ generateHeaderStyles() {
119
+ return `
49
120
  .header {
50
- padding: 20px;
51
- border-bottom: 1px solid #e0e0e0;
121
+ padding: ${this.SPACING.lg}px;
122
+ border-bottom: ${this.BORDER_STYLES.primary};
52
123
  display: flex;
53
124
  justify-content: space-between;
54
125
  align-items: center;
@@ -56,7 +127,7 @@ class StyleManager {
56
127
 
57
128
  .header h2 {
58
129
  margin: 0;
59
- font-size: 20px;
130
+ font-size: ${this.FONT_SIZES.h2};
60
131
  font-weight: 600;
61
132
  }
62
133
 
@@ -67,8 +138,8 @@ class StyleManager {
67
138
  cursor: pointer;
68
139
  color: #666;
69
140
  padding: 0;
70
- width: 30px;
71
- height: 30px;
141
+ width: ${this.MODAL_SIZES.headerHeight};
142
+ height: ${this.MODAL_SIZES.headerHeight};
72
143
  display: flex;
73
144
  align-items: center;
74
145
  justify-content: center;
@@ -78,29 +149,38 @@ class StyleManager {
78
149
  .close:hover {
79
150
  background: #f0f0f0;
80
151
  }
81
-
152
+ `;
153
+ }
154
+ // ============================================================================
155
+ // COMPONENT STYLES - BODY & FORM
156
+ // ============================================================================
157
+ generateBodyStyles() {
158
+ return `
82
159
  .body {
83
- padding: 20px;
160
+ padding: ${this.SPACING.lg}px;
84
161
  }
85
-
162
+ `;
163
+ }
164
+ generateFormStyles() {
165
+ return `
86
166
  .form-group {
87
- margin-bottom: 20px;
167
+ margin-bottom: ${this.SPACING.lg}px;
88
168
  }
89
169
 
90
170
  .label {
91
171
  display: block;
92
- margin-bottom: 8px;
172
+ margin-bottom: ${this.SPACING.xs}px;
93
173
  font-weight: 500;
94
- font-size: 14px;
174
+ font-size: ${this.FONT_SIZES.label};
95
175
  }
96
176
 
97
177
  .input,
98
178
  .textarea {
99
179
  width: 100%;
100
- padding: 10px;
101
- border: 1px solid #ddd;
180
+ padding: ${this.SPACING.xs}px;
181
+ border: ${this.BORDER_STYLES.light};
102
182
  border-radius: ${this.config.borderRadius};
103
- font-size: 14px;
183
+ font-size: ${this.FONT_SIZES.body};
104
184
  font-family: ${this.config.fontFamily};
105
185
  box-sizing: border-box;
106
186
  }
@@ -116,40 +196,92 @@ class StyleManager {
116
196
  resize: vertical;
117
197
  }
118
198
 
119
- .screenshot-container {
120
- margin-top: 10px;
121
- position: relative;
199
+ .checkbox-group {
200
+ display: flex;
201
+ align-items: center;
202
+ gap: ${this.SPACING.xs}px;
203
+ margin-top: ${this.SPACING.md}px;
122
204
  }
123
205
 
124
- .screenshot {
125
- max-width: 100%;
126
- border: 1px solid #ddd;
127
- border-radius: ${this.config.borderRadius};
206
+ .checkbox {
207
+ width: 18px;
208
+ height: 18px;
209
+ cursor: pointer;
128
210
  }
129
211
 
130
- .redaction-canvas {
131
- position: absolute;
132
- top: 0;
133
- left: 0;
134
- cursor: crosshair;
135
- border: 2px solid ${this.config.primaryColor};
212
+ .checkbox-label {
213
+ margin: 0;
214
+ font-size: ${this.FONT_SIZES.body};
215
+ cursor: pointer;
216
+ user-select: none;
217
+ }
218
+
219
+ .error {
220
+ color: ${this.config.dangerColor};
221
+ font-size: ${this.FONT_SIZES.small};
222
+ margin-top: 4px;
223
+ }
224
+ `;
225
+ }
226
+ // ============================================================================
227
+ // COMPONENT STYLES - BUTTONS & CONTROLS
228
+ // ============================================================================
229
+ generateButtonStyles() {
230
+ return `
231
+ .footer {
232
+ padding: ${this.SPACING.lg}px;
233
+ border-top: ${this.BORDER_STYLES.primary};
234
+ display: flex;
235
+ justify-content: flex-end;
236
+ gap: ${this.SPACING.xs}px;
237
+ }
238
+
239
+ .btn {
240
+ padding: ${this.SPACING.xs}px ${this.SPACING.md}px;
241
+ border: none;
136
242
  border-radius: ${this.config.borderRadius};
243
+ cursor: pointer;
244
+ font-size: ${this.FONT_SIZES.body};
245
+ font-weight: 500;
246
+ }
247
+
248
+ .btn-primary {
249
+ background: ${this.config.primaryColor};
250
+ color: white;
251
+ }
252
+
253
+ .btn-primary:hover {
254
+ opacity: 0.9;
255
+ }
256
+
257
+ .btn-primary:disabled {
258
+ opacity: 0.5;
259
+ cursor: not-allowed;
260
+ }
261
+
262
+ .btn-secondary {
263
+ background: #6c757d;
264
+ color: white;
265
+ }
266
+
267
+ .btn-secondary:hover {
268
+ opacity: 0.9;
137
269
  }
138
270
 
139
271
  .redaction-controls {
140
- margin-top: 10px;
272
+ margin-top: ${this.SPACING.xs}px;
141
273
  display: flex;
142
- gap: 10px;
274
+ gap: ${this.SPACING.xs}px;
143
275
  }
144
276
 
145
277
  .btn-redact,
146
278
  .btn-clear {
147
- padding: 8px 16px;
148
- border: 1px solid #ddd;
279
+ padding: ${this.SPACING.xs}px ${this.SPACING.md}px;
280
+ border: ${this.BORDER_STYLES.light};
149
281
  border-radius: ${this.config.borderRadius};
150
282
  background: white;
151
283
  cursor: pointer;
152
- font-size: 14px;
284
+ font-size: ${this.FONT_SIZES.body};
153
285
  }
154
286
 
155
287
  .btn-redact:hover,
@@ -163,17 +295,43 @@ class StyleManager {
163
295
  border-color: ${this.config.primaryColor};
164
296
  }
165
297
 
298
+ .screenshot-container {
299
+ margin-top: ${this.SPACING.xs}px;
300
+ position: relative;
301
+ }
302
+
303
+ .screenshot {
304
+ max-width: 100%;
305
+ border: ${this.BORDER_STYLES.light};
306
+ border-radius: ${this.config.borderRadius};
307
+ }
308
+
309
+ .redaction-canvas {
310
+ position: absolute;
311
+ top: 0;
312
+ left: 0;
313
+ cursor: crosshair;
314
+ border: 2px solid ${this.config.primaryColor};
315
+ border-radius: ${this.config.borderRadius};
316
+ }
317
+ `;
318
+ }
319
+ // ============================================================================
320
+ // COMPONENT STYLES - PII DETECTION
321
+ // ============================================================================
322
+ generatePIIStyles() {
323
+ return `
166
324
  .pii-section {
167
- margin-top: 20px;
168
- padding: 15px;
325
+ margin-top: ${this.SPACING.lg}px;
326
+ padding: ${this.SPACING.md}px;
169
327
  background: #fff3cd;
170
328
  border: 1px solid #ffc107;
171
329
  border-radius: ${this.config.borderRadius};
172
330
  }
173
331
 
174
332
  .pii-title {
175
- margin: 0 0 10px 0;
176
- font-size: 14px;
333
+ margin: 0 0 ${this.SPACING.xs}px 0;
334
+ font-size: ${this.FONT_SIZES.body};
177
335
  font-weight: 600;
178
336
  color: #856404;
179
337
  }
@@ -181,7 +339,7 @@ class StyleManager {
181
339
  .pii-list {
182
340
  margin: 0;
183
341
  padding-left: 20px;
184
- font-size: 13px;
342
+ font-size: ${this.FONT_SIZES.sr};
185
343
  color: #856404;
186
344
  }
187
345
 
@@ -192,61 +350,16 @@ class StyleManager {
192
350
  background: #ffc107;
193
351
  color: #856404;
194
352
  border-radius: 12px;
195
- font-size: 12px;
353
+ font-size: ${this.FONT_SIZES.small};
196
354
  font-weight: 500;
197
355
  }
198
-
199
- .checkbox-group {
200
- display: flex;
201
- align-items: center;
202
- gap: 8px;
203
- margin-top: 15px;
204
- }
205
-
206
- .checkbox {
207
- width: 18px;
208
- height: 18px;
209
- cursor: pointer;
210
- }
211
-
212
- .checkbox-label {
213
- margin: 0;
214
- font-size: 14px;
215
- cursor: pointer;
216
- user-select: none;
217
- }
218
-
219
- .footer {
220
- padding: 20px;
221
- border-top: 1px solid #e0e0e0;
222
- display: flex;
223
- justify-content: flex-end;
224
- gap: 10px;
225
- }
226
-
227
- .btn {
228
- padding: 10px 20px;
229
- border: none;
230
- border-radius: ${this.config.borderRadius};
231
- cursor: pointer;
232
- font-size: 14px;
233
- font-weight: 500;
234
- }
235
-
236
- .btn-primary {
237
- background: ${this.config.primaryColor};
238
- color: white;
239
- }
240
-
241
- .btn-primary:hover {
242
- opacity: 0.9;
243
- }
244
-
245
- .btn-primary:disabled {
246
- opacity: 0.5;
247
- cursor: not-allowed;
248
- }
249
-
356
+ `;
357
+ }
358
+ // ============================================================================
359
+ // COMPONENT STYLES - LOADING STATE
360
+ // ============================================================================
361
+ generateLoadingStyles() {
362
+ return `
250
363
  .btn.loading {
251
364
  position: relative;
252
365
  padding-left: 2.5rem;
@@ -269,7 +382,13 @@ class StyleManager {
269
382
  @keyframes spinner {
270
383
  to { transform: rotate(360deg); }
271
384
  }
272
-
385
+ `;
386
+ }
387
+ // ============================================================================
388
+ // COMPONENT STYLES - ACCESSIBILITY
389
+ // ============================================================================
390
+ generateAccessibilityStyles() {
391
+ return `
273
392
  .sr-only {
274
393
  position: absolute;
275
394
  width: 1px;
@@ -281,20 +400,110 @@ class StyleManager {
281
400
  white-space: nowrap;
282
401
  border-width: 0;
283
402
  }
284
-
285
- .btn-secondary {
286
- background: #6c757d;
287
- color: white;
288
- }
289
-
290
- .btn-secondary:hover {
291
- opacity: 0.9;
403
+ `;
404
+ }
405
+ // ============================================================================
406
+ // RESPONSIVE STYLES - TABLET (≤768px)
407
+ // ============================================================================
408
+ generateTabletResponsiveStyles() {
409
+ return `
410
+ @media (max-width: ${this.BREAKPOINTS.tablet}px) {
411
+ .modal {
412
+ width: 95%;
413
+ max-width: ${this.MODAL_SIZES.tablet};
414
+ }
415
+
416
+ .header {
417
+ padding: ${this.SPACING.md}px;
418
+ }
419
+
420
+ .body {
421
+ padding: ${this.SPACING.md}px;
422
+ }
423
+
424
+ .footer {
425
+ padding: ${this.SPACING.md}px;
426
+ }
427
+
428
+ /* Prevent iOS zoom on input focus (requires 16px minimum) */
429
+ .input,
430
+ .textarea {
431
+ padding: ${this.SPACING.xs}px;
432
+ font-size: 16px;
433
+ }
434
+
435
+ .textarea {
436
+ min-height: 80px;
437
+ }
292
438
  }
293
-
294
- .error {
295
- color: ${this.config.dangerColor};
296
- font-size: 12px;
297
- margin-top: 4px;
439
+ `;
440
+ }
441
+ // ============================================================================
442
+ // RESPONSIVE STYLES - MOBILE (≤480px)
443
+ // ============================================================================
444
+ generateMobileResponsiveStyles() {
445
+ return `
446
+ @media (max-width: ${this.BREAKPOINTS.mobile}px) {
447
+ .modal {
448
+ width: ${this.MODAL_SIZES.mobilePercent};
449
+ max-width: 100%;
450
+ max-height: 95vh;
451
+ }
452
+
453
+ .header {
454
+ padding: ${this.SPACING.sm}px;
455
+ }
456
+
457
+ .header h2 {
458
+ font-size: ${this.FONT_SIZES.h2Mobile};
459
+ }
460
+
461
+ .body {
462
+ padding: ${this.SPACING.sm}px;
463
+ }
464
+
465
+ .footer {
466
+ padding: ${this.SPACING.sm}px;
467
+ flex-direction: column;
468
+ }
469
+
470
+ .btn {
471
+ width: 100%;
472
+ padding: ${this.SPACING.md}px;
473
+ }
474
+
475
+ .input,
476
+ .textarea {
477
+ padding: ${this.SPACING.xs}px;
478
+ }
479
+
480
+ .textarea {
481
+ resize: none;
482
+ }
483
+
484
+ .redaction-controls {
485
+ flex-direction: column;
486
+ }
487
+
488
+ .btn-redact,
489
+ .btn-clear {
490
+ width: 100%;
491
+ }
492
+
493
+ .pii-section {
494
+ padding: ${this.SPACING.sm}px;
495
+ margin-top: ${this.SPACING.md}px;
496
+ }
497
+
498
+ .label {
499
+ font-size: ${this.FONT_SIZES.labelMobile};
500
+ }
501
+
502
+ .close {
503
+ width: 28px;
504
+ height: 28px;
505
+ font-size: 20px;
506
+ }
298
507
  }
299
508
  `;
300
509
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bugspotter/sdk",
3
- "version": "0.2.4-alpha.5",
3
+ "version": "0.3.0",
4
4
  "description": "Professional bug reporting SDK with screenshots, session replay, and automatic error capture for web applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",