@groundbrick/sveltekit-adapter 0.1.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.
Files changed (96) hide show
  1. package/README.md +554 -0
  2. package/dist/analytics/components/GoogleAnalytics.svelte +96 -0
  3. package/dist/analytics/config/analytics.config.d.ts +6 -0
  4. package/dist/analytics/config/analytics.config.d.ts.map +1 -0
  5. package/dist/analytics/config/analytics.config.js +27 -0
  6. package/dist/analytics/config/analytics.config.js.map +1 -0
  7. package/dist/analytics/index.d.ts +7 -0
  8. package/dist/analytics/index.d.ts.map +1 -0
  9. package/dist/analytics/index.js +9 -0
  10. package/dist/analytics/index.js.map +1 -0
  11. package/dist/analytics/interfaces/IAnalyticsService.d.ts +40 -0
  12. package/dist/analytics/interfaces/IAnalyticsService.d.ts.map +1 -0
  13. package/dist/analytics/interfaces/IAnalyticsService.js +2 -0
  14. package/dist/analytics/interfaces/IAnalyticsService.js.map +1 -0
  15. package/dist/analytics/services/AnalyticsService.d.ts +37 -0
  16. package/dist/analytics/services/AnalyticsService.d.ts.map +1 -0
  17. package/dist/analytics/services/AnalyticsService.js +261 -0
  18. package/dist/analytics/services/AnalyticsService.js.map +1 -0
  19. package/dist/analytics/utils/consent.d.ts +52 -0
  20. package/dist/analytics/utils/consent.d.ts.map +1 -0
  21. package/dist/analytics/utils/consent.js +138 -0
  22. package/dist/analytics/utils/consent.js.map +1 -0
  23. package/dist/auth/index.d.ts +10 -0
  24. package/dist/auth/index.d.ts.map +1 -0
  25. package/dist/auth/index.js +49 -0
  26. package/dist/auth/index.js.map +1 -0
  27. package/dist/client/ApiClient.d.ts +17 -0
  28. package/dist/client/ApiClient.d.ts.map +1 -0
  29. package/dist/client/ApiClient.js +184 -0
  30. package/dist/client/ApiClient.js.map +1 -0
  31. package/dist/client/NotificationComponent.d.ts +7 -0
  32. package/dist/client/NotificationComponent.d.ts.map +1 -0
  33. package/dist/client/NotificationComponent.js +131 -0
  34. package/dist/client/NotificationComponent.js.map +1 -0
  35. package/dist/client/apiWrapper.d.ts +324 -0
  36. package/dist/client/apiWrapper.d.ts.map +1 -0
  37. package/dist/client/apiWrapper.js +257 -0
  38. package/dist/client/apiWrapper.js.map +1 -0
  39. package/dist/client/authErrorHandler.d.ts +19 -0
  40. package/dist/client/authErrorHandler.d.ts.map +1 -0
  41. package/dist/client/authErrorHandler.js +40 -0
  42. package/dist/client/authErrorHandler.js.map +1 -0
  43. package/dist/client/hooks.d.ts +11 -0
  44. package/dist/client/hooks.d.ts.map +1 -0
  45. package/dist/client/hooks.js +28 -0
  46. package/dist/client/hooks.js.map +1 -0
  47. package/dist/client/index.d.ts +8 -0
  48. package/dist/client/index.d.ts.map +1 -0
  49. package/dist/client/index.js +13 -0
  50. package/dist/client/index.js.map +1 -0
  51. package/dist/client/jwtDecoder.d.ts +56 -0
  52. package/dist/client/jwtDecoder.d.ts.map +1 -0
  53. package/dist/client/jwtDecoder.js +114 -0
  54. package/dist/client/jwtDecoder.js.map +1 -0
  55. package/dist/client/notifications.d.ts +55 -0
  56. package/dist/client/notifications.d.ts.map +1 -0
  57. package/dist/client/notifications.js +160 -0
  58. package/dist/client/notifications.js.map +1 -0
  59. package/dist/client/stores.d.ts +26 -0
  60. package/dist/client/stores.d.ts.map +1 -0
  61. package/dist/client/stores.js +196 -0
  62. package/dist/client/stores.js.map +1 -0
  63. package/dist/consent/components/CookieConsent.svelte +580 -0
  64. package/dist/consent/config/consent.config.d.ts +7 -0
  65. package/dist/consent/config/consent.config.d.ts.map +1 -0
  66. package/dist/consent/config/consent.config.js +194 -0
  67. package/dist/consent/config/consent.config.js.map +1 -0
  68. package/dist/consent/index.d.ts +5 -0
  69. package/dist/consent/index.d.ts.map +1 -0
  70. package/dist/consent/index.js +7 -0
  71. package/dist/consent/index.js.map +1 -0
  72. package/dist/consent/interfaces/IConsentService.d.ts +121 -0
  73. package/dist/consent/interfaces/IConsentService.d.ts.map +1 -0
  74. package/dist/consent/interfaces/IConsentService.js +2 -0
  75. package/dist/consent/interfaces/IConsentService.js.map +1 -0
  76. package/dist/consent/services/ConsentService.d.ts +39 -0
  77. package/dist/consent/services/ConsentService.d.ts.map +1 -0
  78. package/dist/consent/services/ConsentService.js +302 -0
  79. package/dist/consent/services/ConsentService.js.map +1 -0
  80. package/dist/consent/utils/analytics.d.ts +52 -0
  81. package/dist/consent/utils/analytics.d.ts.map +1 -0
  82. package/dist/consent/utils/analytics.js +181 -0
  83. package/dist/consent/utils/analytics.js.map +1 -0
  84. package/dist/hooks/index.d.ts +14 -0
  85. package/dist/hooks/index.d.ts.map +1 -0
  86. package/dist/hooks/index.js +218 -0
  87. package/dist/hooks/index.js.map +1 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +10 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/types/index.d.ts +88 -0
  93. package/dist/types/index.d.ts.map +1 -0
  94. package/dist/types/index.js +2 -0
  95. package/dist/types/index.js.map +1 -0
  96. package/package.json +87 -0
@@ -0,0 +1,580 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from 'svelte';
3
+ import { ConsentService } from '../services/ConsentService.js';
4
+ import type {
5
+ ConsentState,
6
+ ConsentConfig,
7
+ ConsentPreferences
8
+ } from '../interfaces/IConsentService.js';
9
+ import { DEFAULT_CONSENT_CONFIG } from '../config/consent.config.js';
10
+
11
+ interface CookieConsentProps {
12
+ config?: Partial<ConsentConfig>;
13
+ onConsentChange?: (state: ConsentState) => void;
14
+ position?: 'top' | 'bottom';
15
+ theme?: 'light' | 'dark' | 'auto';
16
+ className?: string;
17
+ }
18
+
19
+ let {
20
+ config = {},
21
+ onConsentChange,
22
+ position = 'bottom',
23
+ theme = 'light',
24
+ className = ''
25
+ }: CookieConsentProps = $props();
26
+
27
+
28
+ let showBanner = $state(false);
29
+ let showPreferences = $state(false);
30
+ let consentService: ConsentService;
31
+ let unsubscribe: (() => void) | null = null;
32
+
33
+ // Current config with defaults
34
+ let currentConfig = $state<ConsentConfig>();
35
+
36
+ // Preferences state - reactive to config changes
37
+ let preferences = $state<Record<string, boolean>>({});
38
+
39
+ onMount(() => {
40
+ consentService = ConsentService.getInstance(
41
+ {
42
+ ...DEFAULT_CONSENT_CONFIG,
43
+ ...config
44
+ });
45
+ currentConfig = consentService.getConfig();
46
+
47
+ // Initialize preferences with default values
48
+ initializePreferences();
49
+
50
+ // Check if consent is required
51
+ if (consentService.isConsentRequired()) {
52
+ showBanner = true;
53
+ }
54
+
55
+ // Subscribe to consent changes
56
+ unsubscribe = consentService.onConsentChange(handleConsentChange);
57
+ });
58
+
59
+ onDestroy(() => {
60
+ if (unsubscribe) {
61
+ unsubscribe();
62
+ }
63
+ });
64
+
65
+ function initializePreferences(): void {
66
+ if (!currentConfig) return;
67
+
68
+ const existingState = consentService.getConsentState();
69
+ const newPreferences: Record<string, boolean> = {};
70
+
71
+ Object.entries(currentConfig.categories).forEach(([category, categoryConfig]) => {
72
+ if (existingState) {
73
+ // Use existing state
74
+ newPreferences[category] = Boolean(existingState[category as keyof ConsentState] ?? categoryConfig.defaultValue ?? false);
75
+ } else {
76
+ // Use default values
77
+ newPreferences[category] = categoryConfig.defaultValue ?? false;
78
+ }
79
+ });
80
+
81
+ preferences = newPreferences;
82
+ }
83
+
84
+ function handleConsentChange(state: ConsentState): void {
85
+ console.log('[CookieConsent] Consent changed:', state);
86
+ onConsentChange?.(state);
87
+
88
+ // Update preferences to match new state
89
+ Object.keys(preferences).forEach(category => {
90
+ preferences[category] = Boolean(state[category as keyof ConsentState] ?? false);
91
+ });
92
+ }
93
+
94
+ async function acceptAll(): Promise<void> {
95
+ await consentService.acceptAll();
96
+ closeBanner();
97
+ }
98
+
99
+ async function rejectAll(): Promise<void> {
100
+ await consentService.rejectAll();
101
+ closeBanner();
102
+ }
103
+
104
+ async function savePreferences(): Promise<void> {
105
+ const consentPreferences: ConsentPreferences = {};
106
+
107
+ Object.entries(preferences).forEach(([category, enabled]) => {
108
+ if (category in currentConfig!.categories) {
109
+ consentPreferences[category as keyof ConsentPreferences] = enabled;
110
+ }
111
+ });
112
+
113
+ await consentService.setConsent(consentPreferences);
114
+ closeBanner();
115
+ }
116
+
117
+ function togglePreferences(): void {
118
+ showPreferences = !showPreferences;
119
+ }
120
+
121
+ function closeBanner(): void {
122
+ showBanner = false;
123
+ showPreferences = false;
124
+ }
125
+
126
+ function updatePreference(category: string, enabled: boolean): void {
127
+ preferences[category] = enabled;
128
+ }
129
+
130
+ // Helper function
131
+ function getBannerClasses() {
132
+ return [
133
+ 'cookie-consent-banner',
134
+ `position-${position}`,
135
+ `theme-${theme}`,
136
+ showPreferences ? 'show-preferences' : '',
137
+ className
138
+ ].filter(Boolean).join(' ');
139
+ }
140
+ </script>
141
+
142
+ {#if showBanner && currentConfig}
143
+ <div class="cookie-consent-overlay">
144
+ <div class={getBannerClasses()}>
145
+ {#if !showPreferences}
146
+ <!-- Basic Banner -->
147
+ <div class="consent-content">
148
+ <div class="consent-header">
149
+ <h3 class="consent-title">{currentConfig.banner.title}</h3>
150
+ <p class="consent-message">{currentConfig.banner.message}</p>
151
+ </div>
152
+
153
+ <div class="consent-actions">
154
+ <button type="button" class="btn btn-secondary" onclick={togglePreferences}>
155
+ {currentConfig.banner.customizeText}
156
+ </button>
157
+ <button type="button" class="btn btn-outline" onclick={rejectAll}>
158
+ {currentConfig.banner.rejectAllText}
159
+ </button>
160
+ <button type="button" class="btn btn-primary" onclick={acceptAll}>
161
+ {currentConfig.banner.acceptAllText}
162
+ </button>
163
+ </div>
164
+ </div>
165
+ {:else}
166
+ <!-- Preferences Panel -->
167
+ <div class="consent-preferences">
168
+ <div class="preferences-header">
169
+ <h3 class="consent-title">Cookie preferences</h3>
170
+ <button type="button" class="btn-close" onclick={togglePreferences} aria-label="Close">
171
+
172
+ </button>
173
+ </div>
174
+
175
+ <div class="preferences-list">
176
+ {#each Object.entries(currentConfig.categories) as [category, categoryConfig]}
177
+ <div class="preference-item">
178
+ <div class="preference-control">
179
+ <div class="switch-container">
180
+ <input
181
+ type="checkbox"
182
+ id="consent-{category}"
183
+ class="switch-input"
184
+ bind:checked={preferences[category]}
185
+ disabled={categoryConfig.required}
186
+ onchange={(e) => updatePreference(category, e.currentTarget.checked)}
187
+ />
188
+ <label for="consent-{category}" class="switch-label">
189
+ <span class="switch-slider"></span>
190
+ </label>
191
+ </div>
192
+ <div class="preference-info">
193
+ <strong class="preference-name">{categoryConfig.name}</strong>
194
+ {#if categoryConfig.required}
195
+ <span class="required-badge">Requerido</span>
196
+ {/if}
197
+ </div>
198
+ </div>
199
+ <p class="preference-description">{categoryConfig.description}</p>
200
+ </div>
201
+ {/each}
202
+ </div>
203
+
204
+ <div class="preferences-actions">
205
+ <button type="button" class="btn btn-outline" onclick={rejectAll}>
206
+ {currentConfig.banner.rejectAllText}
207
+ </button>
208
+ <button type="button" class="btn btn-primary" onclick={savePreferences}>
209
+ {currentConfig.banner.savePreferencesText}
210
+ </button>
211
+ </div>
212
+ </div>
213
+ {/if}
214
+ </div>
215
+ </div>
216
+ {/if}
217
+
218
+ <style>
219
+ .cookie-consent-overlay {
220
+ position: fixed;
221
+ top: 0;
222
+ left: 0;
223
+ right: 0;
224
+ bottom: 0;
225
+ z-index: 9999;
226
+ pointer-events: none;
227
+ display: flex;
228
+ align-items: flex-end;
229
+ justify-content: center;
230
+ }
231
+
232
+ .cookie-consent-banner {
233
+ background: white;
234
+ border-radius: 12px;
235
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
236
+ margin: 20px;
237
+ max-width: 600px;
238
+ width: 100%;
239
+ pointer-events: auto;
240
+ animation: slideUp 0.3s ease-out;
241
+ border: 1px solid #e2e8f0;
242
+ }
243
+
244
+ .cookie-consent-banner.position-top {
245
+ align-self: flex-start;
246
+ animation: slideDown 0.3s ease-out;
247
+ }
248
+
249
+ .cookie-consent-banner.theme-dark {
250
+ background: #1a202c;
251
+ color: white;
252
+ border-color: #2d3748;
253
+ }
254
+
255
+ .cookie-consent-banner.show-preferences {
256
+ max-width: 500px;
257
+ }
258
+
259
+ .consent-content {
260
+ padding: 24px;
261
+ }
262
+
263
+ .consent-preferences {
264
+ padding: 24px;
265
+ max-height: 70vh;
266
+ overflow-y: auto;
267
+ }
268
+
269
+ .consent-header {
270
+ margin-bottom: 20px;
271
+ }
272
+
273
+ .preferences-header {
274
+ display: flex;
275
+ justify-content: space-between;
276
+ align-items: center;
277
+ margin-bottom: 20px;
278
+ }
279
+
280
+ .consent-title {
281
+ font-size: 18px;
282
+ font-weight: 600;
283
+ margin: 0 0 8px 0;
284
+ color: inherit;
285
+ }
286
+
287
+ .consent-message {
288
+ font-size: 14px;
289
+ color: #64748b;
290
+ margin: 0;
291
+ line-height: 1.5;
292
+ }
293
+
294
+ .theme-dark .consent-message {
295
+ color: #a0aec0;
296
+ }
297
+
298
+ .consent-actions {
299
+ display: flex;
300
+ gap: 12px;
301
+ flex-wrap: wrap;
302
+ justify-content: flex-end;
303
+ margin-top: 20px;
304
+ }
305
+
306
+ .preferences-actions {
307
+ display: flex;
308
+ gap: 12px;
309
+ justify-content: flex-end;
310
+ margin-top: 24px;
311
+ padding-top: 20px;
312
+ border-top: 1px solid #e2e8f0;
313
+ }
314
+
315
+ .theme-dark .preferences-actions {
316
+ border-top-color: #2d3748;
317
+ }
318
+
319
+ .preferences-list {
320
+ display: flex;
321
+ flex-direction: column;
322
+ gap: 20px;
323
+ }
324
+
325
+ .preference-item {
326
+ padding: 16px;
327
+ border: 1px solid #e2e8f0;
328
+ border-radius: 8px;
329
+ background: #f8fafc;
330
+ }
331
+
332
+ .theme-dark .preference-item {
333
+ background: #2d3748;
334
+ border-color: #4a5568;
335
+ }
336
+
337
+ .preference-control {
338
+ display: flex;
339
+ align-items: center;
340
+ gap: 12px;
341
+ margin-bottom: 8px;
342
+ }
343
+
344
+ .preference-info {
345
+ display: flex;
346
+ align-items: center;
347
+ gap: 8px;
348
+ flex: 1;
349
+ }
350
+
351
+ .preference-name {
352
+ font-weight: 500;
353
+ color: inherit;
354
+ }
355
+
356
+ .required-badge {
357
+ background: #10b981;
358
+ color: white;
359
+ font-size: 10px;
360
+ font-weight: 500;
361
+ padding: 2px 6px;
362
+ border-radius: 4px;
363
+ text-transform: uppercase;
364
+ letter-spacing: 0.5px;
365
+ }
366
+
367
+ .preference-description {
368
+ font-size: 13px;
369
+ color: #64748b;
370
+ margin: 0;
371
+ line-height: 1.4;
372
+ }
373
+
374
+ .theme-dark .preference-description {
375
+ color: #a0aec0;
376
+ }
377
+
378
+ /* Switch Styles */
379
+ .switch-container {
380
+ position: relative;
381
+ display: flex;
382
+ }
383
+
384
+ .switch-input {
385
+ opacity: 0;
386
+ width: 0;
387
+ height: 0;
388
+ }
389
+
390
+ .switch-label {
391
+ display: inline-block;
392
+ width: 44px;
393
+ height: 24px;
394
+ cursor: pointer;
395
+ }
396
+
397
+ .switch-slider {
398
+ position: absolute;
399
+ top: 0;
400
+ left: 0;
401
+ right: 0;
402
+ bottom: 0;
403
+ background-color: #cbd5e0;
404
+ border-radius: 24px;
405
+ transition: 0.2s;
406
+ height: 1.5rem;
407
+ }
408
+
409
+ .switch-slider:before {
410
+ position: absolute;
411
+ content: "";
412
+ height: 18px;
413
+ width: 18px;
414
+ left: 3px;
415
+ bottom: 3px;
416
+ background-color: white;
417
+ border-radius: 50%;
418
+ transition: 0.2s;
419
+ }
420
+
421
+ .switch-input:checked + .switch-label .switch-slider {
422
+ background-color: #3b82f6;
423
+ }
424
+
425
+ .switch-input:checked + .switch-label .switch-slider:before {
426
+ transform: translateX(20px);
427
+ }
428
+
429
+ .switch-input:disabled + .switch-label {
430
+ opacity: 0.6;
431
+ cursor: not-allowed;
432
+ }
433
+
434
+ /* Button Styles */
435
+ .btn {
436
+ padding: 10px 16px;
437
+ border-radius: 8px;
438
+ font-size: 14px;
439
+ font-weight: 500;
440
+ cursor: pointer;
441
+ transition: all 0.2s ease;
442
+ border: 1px solid transparent;
443
+ display: inline-flex;
444
+ align-items: center;
445
+ justify-content: center;
446
+ min-height: 40px;
447
+ }
448
+
449
+ .btn:hover {
450
+ transform: translateY(-1px);
451
+ }
452
+
453
+ .btn:active {
454
+ transform: translateY(0);
455
+ }
456
+
457
+ .btn-primary {
458
+ background: #3b82f6;
459
+ color: white;
460
+ border-color: #3b82f6;
461
+ }
462
+
463
+ .btn-primary:hover {
464
+ background: #2563eb;
465
+ border-color: #2563eb;
466
+ }
467
+
468
+ .btn-secondary {
469
+ background: #64748b;
470
+ color: white;
471
+ border-color: #64748b;
472
+ }
473
+
474
+ .btn-secondary:hover {
475
+ background: #475569;
476
+ border-color: #475569;
477
+ }
478
+
479
+ .btn-outline {
480
+ background: transparent;
481
+ color: #64748b;
482
+ border-color: #cbd5e0;
483
+ }
484
+
485
+ .btn-outline:hover {
486
+ background: #f1f5f9;
487
+ border-color: #94a3b8;
488
+ }
489
+
490
+ .theme-dark .btn-outline {
491
+ color: #a0aec0;
492
+ border-color: #4a5568;
493
+ }
494
+
495
+ .theme-dark .btn-outline:hover {
496
+ background: #2d3748;
497
+ border-color: #718096;
498
+ }
499
+
500
+ .btn-close {
501
+ background: none;
502
+ border: none;
503
+ font-size: 18px;
504
+ cursor: pointer;
505
+ color: #64748b;
506
+ width: 32px;
507
+ height: 32px;
508
+ display: flex;
509
+ align-items: center;
510
+ justify-content: center;
511
+ border-radius: 6px;
512
+ transition: all 0.2s ease;
513
+ }
514
+
515
+ .btn-close:hover {
516
+ background: #f1f5f9;
517
+ color: #374151;
518
+ }
519
+
520
+ .theme-dark .btn-close {
521
+ color: #a0aec0;
522
+ }
523
+
524
+ .theme-dark .btn-close:hover {
525
+ background: #374151;
526
+ color: white;
527
+ }
528
+
529
+ /* Animations */
530
+ @keyframes slideUp {
531
+ from {
532
+ transform: translateY(100%);
533
+ opacity: 0;
534
+ }
535
+ to {
536
+ transform: translateY(0);
537
+ opacity: 1;
538
+ }
539
+ }
540
+
541
+ @keyframes slideDown {
542
+ from {
543
+ transform: translateY(-100%);
544
+ opacity: 0;
545
+ }
546
+ to {
547
+ transform: translateY(0);
548
+ opacity: 1;
549
+ }
550
+ }
551
+
552
+ /* Responsive */
553
+ @media (max-width: 768px) {
554
+ .cookie-consent-banner {
555
+ margin: 0;
556
+ border-radius: 0;
557
+ max-width: none;
558
+ width: 100%;
559
+ }
560
+
561
+ .consent-actions,
562
+ .preferences-actions {
563
+ flex-direction: column;
564
+ }
565
+
566
+ .btn {
567
+ width: 100%;
568
+ }
569
+
570
+ .preference-control {
571
+ flex-direction: column;
572
+ align-items: flex-start;
573
+ gap: 8px;
574
+ }
575
+
576
+ .switch-container {
577
+ align-self: flex-start;
578
+ }
579
+ }
580
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { ConsentConfig } from '../interfaces/IConsentService.js';
2
+ export declare const DEFAULT_CONSENT_CONFIG: ConsentConfig;
3
+ export declare const GDPR_CONFIG: Partial<ConsentConfig>;
4
+ export declare const CCPA_CONFIG: Partial<ConsentConfig>;
5
+ export declare const GENERIC_CONFIG: Partial<ConsentConfig>;
6
+ export declare function getRegionConfig(region?: string): Partial<ConsentConfig>;
7
+ //# sourceMappingURL=consent.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.config.d.ts","sourceRoot":"","sources":["../../../src/consent/config/consent.config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEtE,eAAO,MAAM,sBAAsB,EAAE,aAmG3B,CAAC;AAGX,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,aAAa,CA6B9C,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,OAAO,CAAC,aAAa,CA6B9C,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,aAAa,CAoBjD,CAAC;AAGF,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAcvE"}