@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.
- package/README.md +554 -0
- package/dist/analytics/components/GoogleAnalytics.svelte +96 -0
- package/dist/analytics/config/analytics.config.d.ts +6 -0
- package/dist/analytics/config/analytics.config.d.ts.map +1 -0
- package/dist/analytics/config/analytics.config.js +27 -0
- package/dist/analytics/config/analytics.config.js.map +1 -0
- package/dist/analytics/index.d.ts +7 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/index.js +9 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/interfaces/IAnalyticsService.d.ts +40 -0
- package/dist/analytics/interfaces/IAnalyticsService.d.ts.map +1 -0
- package/dist/analytics/interfaces/IAnalyticsService.js +2 -0
- package/dist/analytics/interfaces/IAnalyticsService.js.map +1 -0
- package/dist/analytics/services/AnalyticsService.d.ts +37 -0
- package/dist/analytics/services/AnalyticsService.d.ts.map +1 -0
- package/dist/analytics/services/AnalyticsService.js +261 -0
- package/dist/analytics/services/AnalyticsService.js.map +1 -0
- package/dist/analytics/utils/consent.d.ts +52 -0
- package/dist/analytics/utils/consent.d.ts.map +1 -0
- package/dist/analytics/utils/consent.js +138 -0
- package/dist/analytics/utils/consent.js.map +1 -0
- package/dist/auth/index.d.ts +10 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +49 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/client/ApiClient.d.ts +17 -0
- package/dist/client/ApiClient.d.ts.map +1 -0
- package/dist/client/ApiClient.js +184 -0
- package/dist/client/ApiClient.js.map +1 -0
- package/dist/client/NotificationComponent.d.ts +7 -0
- package/dist/client/NotificationComponent.d.ts.map +1 -0
- package/dist/client/NotificationComponent.js +131 -0
- package/dist/client/NotificationComponent.js.map +1 -0
- package/dist/client/apiWrapper.d.ts +324 -0
- package/dist/client/apiWrapper.d.ts.map +1 -0
- package/dist/client/apiWrapper.js +257 -0
- package/dist/client/apiWrapper.js.map +1 -0
- package/dist/client/authErrorHandler.d.ts +19 -0
- package/dist/client/authErrorHandler.d.ts.map +1 -0
- package/dist/client/authErrorHandler.js +40 -0
- package/dist/client/authErrorHandler.js.map +1 -0
- package/dist/client/hooks.d.ts +11 -0
- package/dist/client/hooks.d.ts.map +1 -0
- package/dist/client/hooks.js +28 -0
- package/dist/client/hooks.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +13 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/jwtDecoder.d.ts +56 -0
- package/dist/client/jwtDecoder.d.ts.map +1 -0
- package/dist/client/jwtDecoder.js +114 -0
- package/dist/client/jwtDecoder.js.map +1 -0
- package/dist/client/notifications.d.ts +55 -0
- package/dist/client/notifications.d.ts.map +1 -0
- package/dist/client/notifications.js +160 -0
- package/dist/client/notifications.js.map +1 -0
- package/dist/client/stores.d.ts +26 -0
- package/dist/client/stores.d.ts.map +1 -0
- package/dist/client/stores.js +196 -0
- package/dist/client/stores.js.map +1 -0
- package/dist/consent/components/CookieConsent.svelte +580 -0
- package/dist/consent/config/consent.config.d.ts +7 -0
- package/dist/consent/config/consent.config.d.ts.map +1 -0
- package/dist/consent/config/consent.config.js +194 -0
- package/dist/consent/config/consent.config.js.map +1 -0
- package/dist/consent/index.d.ts +5 -0
- package/dist/consent/index.d.ts.map +1 -0
- package/dist/consent/index.js +7 -0
- package/dist/consent/index.js.map +1 -0
- package/dist/consent/interfaces/IConsentService.d.ts +121 -0
- package/dist/consent/interfaces/IConsentService.d.ts.map +1 -0
- package/dist/consent/interfaces/IConsentService.js +2 -0
- package/dist/consent/interfaces/IConsentService.js.map +1 -0
- package/dist/consent/services/ConsentService.d.ts +39 -0
- package/dist/consent/services/ConsentService.d.ts.map +1 -0
- package/dist/consent/services/ConsentService.js +302 -0
- package/dist/consent/services/ConsentService.js.map +1 -0
- package/dist/consent/utils/analytics.d.ts +52 -0
- package/dist/consent/utils/analytics.d.ts.map +1 -0
- package/dist/consent/utils/analytics.js +181 -0
- package/dist/consent/utils/analytics.js.map +1 -0
- package/dist/hooks/index.d.ts +14 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +218 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +88 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ApiClientConfig, RequestOptions } from '../types/index.js';
|
|
2
|
+
export declare class ApiClient {
|
|
3
|
+
private config;
|
|
4
|
+
private logger;
|
|
5
|
+
constructor(config: ApiClientConfig);
|
|
6
|
+
get<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
|
|
7
|
+
post<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions): Promise<T>;
|
|
8
|
+
put<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions): Promise<T>;
|
|
9
|
+
patch<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions): Promise<T>;
|
|
10
|
+
delete<T = unknown>(endpoint: string, options?: RequestOptions): Promise<T>;
|
|
11
|
+
private request;
|
|
12
|
+
private prepareBody;
|
|
13
|
+
private fetchWithTimeout;
|
|
14
|
+
requestWithRetry<T>(endpoint: string, options?: RequestOptions, retries?: number): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createApiClient(config: ApiClientConfig): ApiClient;
|
|
17
|
+
//# sourceMappingURL=ApiClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClient.d.ts","sourceRoot":"","sources":["../../src/client/ApiClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAe,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtF,qBAAa,SAAS;IAGN,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,MAAM,CAAS;gBAEH,MAAM,EAAE,eAAe;IAerC,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAIxE,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IASzF,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAQxF,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAQ1F,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;YAQnE,OAAO;IAwFrB,OAAO,CAAC,WAAW;YAYL,gBAAgB;IAuBxB,gBAAgB,CAAC,CAAC,EACpB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,cAAmB,EAC5B,OAAO,GAAE,MAAiC,GAC3C,OAAO,CAAC,CAAC,CAAC;CAgChB;AAMD,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAElE"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { createLogger } from '@groundbrick/logger';
|
|
2
|
+
export class ApiClient {
|
|
3
|
+
config;
|
|
4
|
+
logger;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.logger = createLogger().child('api-client');
|
|
8
|
+
}
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// AUTHENTICATION STATUS
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Authentication is now handled via HttpOnly cookies server-side
|
|
13
|
+
// Client no longer needs to manage tokens
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// HTTP METHODS
|
|
16
|
+
// ============================================================================
|
|
17
|
+
async get(endpoint, options) {
|
|
18
|
+
return this.request(endpoint, { ...options, method: 'GET' });
|
|
19
|
+
}
|
|
20
|
+
async post(endpoint, data, options) {
|
|
21
|
+
const resp = await this.request(endpoint, {
|
|
22
|
+
...options,
|
|
23
|
+
method: 'POST',
|
|
24
|
+
body: this.prepareBody(data)
|
|
25
|
+
});
|
|
26
|
+
return resp;
|
|
27
|
+
}
|
|
28
|
+
async put(endpoint, data, options) {
|
|
29
|
+
return this.request(endpoint, {
|
|
30
|
+
...options,
|
|
31
|
+
method: 'PUT',
|
|
32
|
+
body: this.prepareBody(data)
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
async patch(endpoint, data, options) {
|
|
36
|
+
return this.request(endpoint, {
|
|
37
|
+
...options,
|
|
38
|
+
method: 'PATCH',
|
|
39
|
+
body: this.prepareBody(data)
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async delete(endpoint, options) {
|
|
43
|
+
return this.request(endpoint, { ...options, method: 'DELETE' });
|
|
44
|
+
}
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// CORE REQUEST METHOD
|
|
47
|
+
// ============================================================================
|
|
48
|
+
async request(endpoint, options = {}) {
|
|
49
|
+
const url = `${this.config.baseUrl}${endpoint}`;
|
|
50
|
+
const timeout = options.timeout || this.config.timeout || 10000;
|
|
51
|
+
this.logger.debug('Making API request', {
|
|
52
|
+
method: options.method || 'GET',
|
|
53
|
+
url,
|
|
54
|
+
credentials: 'include' // HttpOnly cookies sent automatically
|
|
55
|
+
});
|
|
56
|
+
// Prepare headers - don't set Content-Type for FormData (browser will set with boundary)
|
|
57
|
+
const headers = {
|
|
58
|
+
...this.config.defaultHeaders,
|
|
59
|
+
...options.headers,
|
|
60
|
+
};
|
|
61
|
+
// Handle Content-Type based on body type
|
|
62
|
+
if (options.body instanceof FormData) {
|
|
63
|
+
// For FormData, remove any Content-Type header to let browser set it with boundary
|
|
64
|
+
delete headers['Content-Type'];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// For regular requests, ensure JSON content type
|
|
68
|
+
headers['Content-Type'] = 'application/json';
|
|
69
|
+
}
|
|
70
|
+
// HttpOnly cookies are sent automatically with credentials: 'include'
|
|
71
|
+
// Create request options
|
|
72
|
+
const requestOptions = {
|
|
73
|
+
...options,
|
|
74
|
+
headers,
|
|
75
|
+
credentials: 'include', // Include cookies for authentication
|
|
76
|
+
};
|
|
77
|
+
let response;
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
try {
|
|
80
|
+
// Make request with timeout
|
|
81
|
+
response = await this.fetchWithTimeout(url, requestOptions, timeout);
|
|
82
|
+
const duration = Date.now() - startTime;
|
|
83
|
+
this.logger.debug('API request completed', {
|
|
84
|
+
url,
|
|
85
|
+
status: response.status,
|
|
86
|
+
duration
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
const duration = Date.now() - startTime;
|
|
91
|
+
this.logger.error('API request failed', error, {
|
|
92
|
+
url,
|
|
93
|
+
duration,
|
|
94
|
+
method: options.method
|
|
95
|
+
});
|
|
96
|
+
throw new Error(`Network error: ${error.message}`);
|
|
97
|
+
}
|
|
98
|
+
// Handle response
|
|
99
|
+
let responseData;
|
|
100
|
+
try {
|
|
101
|
+
responseData = await response.json();
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
throw new Error('Invalid JSON response from server');
|
|
105
|
+
}
|
|
106
|
+
// Handle error responses
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
const errorMessage = responseData.error || `HTTP ${response.status}: ${response.statusText}`;
|
|
109
|
+
this.logger.warn('API request returned error', {
|
|
110
|
+
url,
|
|
111
|
+
status: response.status,
|
|
112
|
+
error: errorMessage
|
|
113
|
+
});
|
|
114
|
+
// Just throw the error with status info - let the caller handle it
|
|
115
|
+
return responseData;
|
|
116
|
+
}
|
|
117
|
+
return responseData;
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// UTILITY METHODS
|
|
121
|
+
// ============================================================================
|
|
122
|
+
prepareBody(data) {
|
|
123
|
+
if (!data)
|
|
124
|
+
return undefined;
|
|
125
|
+
// If it's already FormData, use it as-is
|
|
126
|
+
if (data instanceof FormData) {
|
|
127
|
+
return data;
|
|
128
|
+
}
|
|
129
|
+
// For regular objects, stringify to JSON
|
|
130
|
+
return JSON.stringify(data);
|
|
131
|
+
}
|
|
132
|
+
async fetchWithTimeout(url, options, timeout) {
|
|
133
|
+
const controller = new AbortController();
|
|
134
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
135
|
+
try {
|
|
136
|
+
const response = await fetch(url, {
|
|
137
|
+
...options,
|
|
138
|
+
signal: controller.signal
|
|
139
|
+
});
|
|
140
|
+
return response;
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
clearTimeout(timeoutId);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// RETRY MECHANISM
|
|
148
|
+
// ============================================================================
|
|
149
|
+
async requestWithRetry(endpoint, options = {}, retries = this.config.retries || 3) {
|
|
150
|
+
let lastError;
|
|
151
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
152
|
+
try {
|
|
153
|
+
return await this.request(endpoint, options);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
lastError = error;
|
|
157
|
+
this.logger.warn('Request attempt failed', {
|
|
158
|
+
attempt,
|
|
159
|
+
retries,
|
|
160
|
+
error: lastError.message,
|
|
161
|
+
endpoint
|
|
162
|
+
});
|
|
163
|
+
// Don't retry on authentication errors or client errors (4xx)
|
|
164
|
+
if (lastError.message.includes('Authentication required') ||
|
|
165
|
+
lastError.message.includes('HTTP 4')) {
|
|
166
|
+
throw lastError;
|
|
167
|
+
}
|
|
168
|
+
// Wait before retrying (exponential backoff)
|
|
169
|
+
if (attempt < retries) {
|
|
170
|
+
const delay = Math.pow(2, attempt - 1) * 1000;
|
|
171
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
throw lastError;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// FACTORY FUNCTION
|
|
180
|
+
// ============================================================================
|
|
181
|
+
export function createApiClient(config) {
|
|
182
|
+
return new ApiClient(config);
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=ApiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiClient.js","sourceRoot":"","sources":["../../src/client/ApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAe,MAAM,qBAAqB,CAAC;AAGhE,MAAM,OAAO,SAAS;IAGE;IAFZ,MAAM,CAAS;IAEvB,YAAoB,MAAuB;QAAvB,WAAM,GAAN,MAAM,CAAiB;QACvC,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC;IAED,+EAA+E;IAC/E,wBAAwB;IACxB,+EAA+E;IAE/E,iEAAiE;IACjE,0CAA0C;IAE1C,+EAA+E;IAC/E,eAAe;IACf,+EAA+E;IAE/E,KAAK,CAAC,GAAG,CAAc,QAAgB,EAAE,OAAwB;QAC7D,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,IAAI,CAAc,QAAgB,EAAE,IAAc,EAAE,OAAwB;QAC9E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE;YACzC,GAAG,OAAO;YACV,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;SAC/B,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAc,QAAgB,EAAE,IAAc,EAAE,OAAwB;QAC7E,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE;YAC7B,GAAG,OAAO;YACV,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;SAC/B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,KAAK,CAAc,QAAgB,EAAE,IAAc,EAAE,OAAwB;QAC/E,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE;YAC7B,GAAG,OAAO;YACV,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;SAC/B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,MAAM,CAAc,QAAgB,EAAE,OAAwB;QAChE,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,+EAA+E;IAC/E,sBAAsB;IACtB,+EAA+E;IAEvE,KAAK,CAAC,OAAO,CAAI,QAAgB,EAAE,UAA0B,EAAE;QACnE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;QAEhE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE;YACpC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,GAAG;YACH,WAAW,EAAE,SAAS,CAAC,sCAAsC;SAChE,CAAC,CAAC;QAEH,yFAAyF;QACzF,MAAM,OAAO,GAAQ;YACjB,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc;YAC7B,GAAG,OAAO,CAAC,OAAO;SACrB,CAAC;QAEF,yCAAyC;QACzC,IAAI,OAAO,CAAC,IAAI,YAAY,QAAQ,EAAE,CAAC;YACnC,mFAAmF;YACnF,OAAO,OAAO,CAAC,cAAc,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACJ,iDAAiD;YACjD,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;QACjD,CAAC;QAED,sEAAsE;QAEtE,yBAAyB;QACzB,MAAM,cAAc,GAAgB;YAChC,GAAG,OAAO;YACV,OAAO;YACP,WAAW,EAAE,SAAS,EAAE,qCAAqC;SAChE,CAAC;QAEF,IAAI,QAAkB,CAAC;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACD,4BAA4B;YAC5B,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;YAErE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE;gBACvC,GAAG;gBACH,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,QAAQ;aACX,CAAC,CAAC;QAEP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAc,EAAE;gBACpD,GAAG;gBACH,QAAQ;gBACR,MAAM,EAAE,OAAO,CAAC,MAAM;aACzB,CAAC,CAAC;YACH,MAAM,IAAI,KAAK,CAAC,kBAAmB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,kBAAkB;QAClB,IAAI,YAA4B,CAAC;QAEjC,IAAI,CAAC;YACD,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAoB,CAAC;QAC3D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACzD,CAAC;QAED,yBAAyB;QACzB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,IAAI,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;YAE7F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE;gBAC3C,GAAG;gBACH,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,KAAK,EAAE,YAAY;aACtB,CAAC,CAAC;YAEH,mEAAmE;YACnE,OAAO,YAAiB,CAAC;QAC7B,CAAC;QAED,OAAO,YAAiB,CAAC;IAC7B,CAAC;IAED,+EAA+E;IAC/E,kBAAkB;IAClB,+EAA+E;IAEvE,WAAW,CAAC,IAAc;QAC9B,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAE5B,yCAAyC;QACzC,IAAI,IAAI,YAAY,QAAQ,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,yCAAyC;QACzC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC1B,GAAW,EACX,OAAoB,EACpB,OAAe;QAEf,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC9B,GAAG,OAAO;gBACV,MAAM,EAAE,UAAU,CAAC,MAAM;aAC5B,CAAC,CAAC;YACH,OAAO,QAAQ,CAAC;QACpB,CAAC;gBAAS,CAAC;YACP,YAAY,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC;IAED,+EAA+E;IAC/E,kBAAkB;IAClB,+EAA+E;IAE/E,KAAK,CAAC,gBAAgB,CAClB,QAAgB,EAChB,UAA0B,EAAE,EAC5B,UAAkB,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC;QAE1C,IAAI,SAAgB,CAAC;QAErB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YAClD,IAAI,CAAC;gBACD,OAAO,MAAM,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,SAAS,GAAG,KAAc,CAAC;gBAE3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE;oBACvC,OAAO;oBACP,OAAO;oBACP,KAAK,EAAE,SAAS,CAAC,OAAO;oBACxB,QAAQ;iBACX,CAAC,CAAC;gBAEH,8DAA8D;gBAC9D,IAAI,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC;oBACrD,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,MAAM,SAAS,CAAC;gBACpB,CAAC;gBAED,6CAA6C;gBAC7C,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;oBACpB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;oBAC9C,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC7D,CAAC;YACL,CAAC;QACL,CAAC;QAED,MAAM,SAAU,CAAC;IACrB,CAAC;CACJ;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,MAAM,UAAU,eAAe,CAAC,MAAuB;IACnD,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple notification component for SvelteKit apps
|
|
3
|
+
* Copy this to your app and customize as needed
|
|
4
|
+
*/
|
|
5
|
+
export declare const NotificationTemplate = "\n<script lang=\"ts\">\n import { notifications, removeNotification } from '@groundbrick/sveltekit-adapter/client';\n \n function getNotificationClass(type: string): string {\n const baseClass = 'alert alert-dismissible fade show';\n switch (type) {\n case 'success':\n return baseClass + ' alert-success';\n case 'error':\n return baseClass + ' alert-danger';\n case 'warning':\n return baseClass + ' alert-warning';\n case 'info':\n return baseClass + ' alert-info';\n default:\n return baseClass + ' alert-secondary';\n }\n }\n\n function getNotificationIcon(type: string): string {\n switch (type) {\n case 'success':\n return '\u2705';\n case 'error':\n return '\u274C';\n case 'warning':\n return '\u26A0\uFE0F';\n case 'info':\n return '\u2139\uFE0F';\n default:\n return '\uD83D\uDCE2';\n }\n }\n</script>\n\n<!-- Notification Container -->\n{#if $notifications.length > 0}\n <div class=\"notification-container position-fixed top-0 end-0 p-3\" style=\"z-index: 1050;\">\n {#each $notifications as notification (notification.id)}\n <div class=\"{getNotificationClass(notification.type)}\" role=\"alert\">\n <div class=\"d-flex align-items-start\">\n <span class=\"me-2\">{getNotificationIcon(notification.type)}</span>\n <div class=\"flex-grow-1\">\n {#if notification.title}\n <h6 class=\"alert-heading mb-1\">{notification.title}</h6>\n {/if}\n <div>{notification.message}</div>\n </div>\n <button \n type=\"button\" \n class=\"btn-close\" \n aria-label=\"Close\"\n on:click={() => removeNotification(notification.id)}\n ></button>\n </div>\n </div>\n {/each}\n </div>\n{/if}\n\n<style>\n .notification-container {\n max-width: 400px;\n }\n \n .alert {\n margin-bottom: 1rem;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n }\n \n @media (max-width: 576px) {\n .notification-container {\n left: 0.75rem;\n right: 0.75rem;\n max-width: none;\n }\n }\n</style>\n";
|
|
6
|
+
export declare const usageInstructions = "\nTo use the notification system in your SvelteKit app:\n\n1. Copy the NotificationTemplate above to a new component file (e.g., src/lib/components/Notifications.svelte)\n\n2. Add it to your app's root layout (src/app.html or src/routes/+layout.svelte):\n\n```svelte\n<script>\n import { useNavigationNotificationClear } from '@groundbrick/sveltekit-adapter/client';\n import Notifications from '$lib/components/Notifications.svelte';\n \n // Enable auto-clearing of notifications on navigation\n useNavigationNotificationClear();\n</script>\n\n<!-- Your app content -->\n<main>\n <slot />\n</main>\n\n<!-- Notifications -->\n<Notifications />\n```\n\n3. Use the notification functions in your pages:\n\n```svelte\n<script>\n import { showSuccess, showError, showWarning, showInfo } from '@groundbrick/sveltekit-adapter/client';\n \n async function saveData() {\n try {\n await apiClient.post('/data', formData);\n showSuccess('Data saved successfully!');\n } catch (error) {\n showError('Failed to save data. Please try again.');\n }\n }\n</script>\n```\n\n4. Customize the notification component styling to match your app's design.\n";
|
|
7
|
+
//# sourceMappingURL=NotificationComponent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationComponent.d.ts","sourceRoot":"","sources":["../../src/client/NotificationComponent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,oBAAoB,2qEA+EhC,CAAC;AAGF,eAAO,MAAM,iBAAiB,spCA2C7B,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple notification component for SvelteKit apps
|
|
3
|
+
* Copy this to your app and customize as needed
|
|
4
|
+
*/
|
|
5
|
+
// This is a template component. Copy to your app's components folder and customize.
|
|
6
|
+
export const NotificationTemplate = `
|
|
7
|
+
<script lang="ts">
|
|
8
|
+
import { notifications, removeNotification } from '@groundbrick/sveltekit-adapter/client';
|
|
9
|
+
|
|
10
|
+
function getNotificationClass(type: string): string {
|
|
11
|
+
const baseClass = 'alert alert-dismissible fade show';
|
|
12
|
+
switch (type) {
|
|
13
|
+
case 'success':
|
|
14
|
+
return baseClass + ' alert-success';
|
|
15
|
+
case 'error':
|
|
16
|
+
return baseClass + ' alert-danger';
|
|
17
|
+
case 'warning':
|
|
18
|
+
return baseClass + ' alert-warning';
|
|
19
|
+
case 'info':
|
|
20
|
+
return baseClass + ' alert-info';
|
|
21
|
+
default:
|
|
22
|
+
return baseClass + ' alert-secondary';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getNotificationIcon(type: string): string {
|
|
27
|
+
switch (type) {
|
|
28
|
+
case 'success':
|
|
29
|
+
return '✅';
|
|
30
|
+
case 'error':
|
|
31
|
+
return '❌';
|
|
32
|
+
case 'warning':
|
|
33
|
+
return '⚠️';
|
|
34
|
+
case 'info':
|
|
35
|
+
return 'ℹ️';
|
|
36
|
+
default:
|
|
37
|
+
return '📢';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<!-- Notification Container -->
|
|
43
|
+
{#if $notifications.length > 0}
|
|
44
|
+
<div class="notification-container position-fixed top-0 end-0 p-3" style="z-index: 1050;">
|
|
45
|
+
{#each $notifications as notification (notification.id)}
|
|
46
|
+
<div class="{getNotificationClass(notification.type)}" role="alert">
|
|
47
|
+
<div class="d-flex align-items-start">
|
|
48
|
+
<span class="me-2">{getNotificationIcon(notification.type)}</span>
|
|
49
|
+
<div class="flex-grow-1">
|
|
50
|
+
{#if notification.title}
|
|
51
|
+
<h6 class="alert-heading mb-1">{notification.title}</h6>
|
|
52
|
+
{/if}
|
|
53
|
+
<div>{notification.message}</div>
|
|
54
|
+
</div>
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
class="btn-close"
|
|
58
|
+
aria-label="Close"
|
|
59
|
+
on:click={() => removeNotification(notification.id)}
|
|
60
|
+
></button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
{/each}
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
.notification-container {
|
|
69
|
+
max-width: 400px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.alert {
|
|
73
|
+
margin-bottom: 1rem;
|
|
74
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@media (max-width: 576px) {
|
|
78
|
+
.notification-container {
|
|
79
|
+
left: 0.75rem;
|
|
80
|
+
right: 0.75rem;
|
|
81
|
+
max-width: none;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
85
|
+
`;
|
|
86
|
+
// Usage instructions
|
|
87
|
+
export const usageInstructions = `
|
|
88
|
+
To use the notification system in your SvelteKit app:
|
|
89
|
+
|
|
90
|
+
1. Copy the NotificationTemplate above to a new component file (e.g., src/lib/components/Notifications.svelte)
|
|
91
|
+
|
|
92
|
+
2. Add it to your app's root layout (src/app.html or src/routes/+layout.svelte):
|
|
93
|
+
|
|
94
|
+
\`\`\`svelte
|
|
95
|
+
<script>
|
|
96
|
+
import { useNavigationNotificationClear } from '@groundbrick/sveltekit-adapter/client';
|
|
97
|
+
import Notifications from '$lib/components/Notifications.svelte';
|
|
98
|
+
|
|
99
|
+
// Enable auto-clearing of notifications on navigation
|
|
100
|
+
useNavigationNotificationClear();
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<!-- Your app content -->
|
|
104
|
+
<main>
|
|
105
|
+
<slot />
|
|
106
|
+
</main>
|
|
107
|
+
|
|
108
|
+
<!-- Notifications -->
|
|
109
|
+
<Notifications />
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
3. Use the notification functions in your pages:
|
|
113
|
+
|
|
114
|
+
\`\`\`svelte
|
|
115
|
+
<script>
|
|
116
|
+
import { showSuccess, showError, showWarning, showInfo } from '@groundbrick/sveltekit-adapter/client';
|
|
117
|
+
|
|
118
|
+
async function saveData() {
|
|
119
|
+
try {
|
|
120
|
+
await apiClient.post('/data', formData);
|
|
121
|
+
showSuccess('Data saved successfully!');
|
|
122
|
+
} catch (error) {
|
|
123
|
+
showError('Failed to save data. Please try again.');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
</script>
|
|
127
|
+
\`\`\`
|
|
128
|
+
|
|
129
|
+
4. Customize the notification component styling to match your app's design.
|
|
130
|
+
`;
|
|
131
|
+
//# sourceMappingURL=NotificationComponent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationComponent.js","sourceRoot":"","sources":["../../src/client/NotificationComponent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+EnC,CAAC;AAEF,qBAAqB;AACrB,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAC"}
|