@thisbefine/analytics 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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +403 -0
  3. package/dist/core/analytics.d.ts +123 -0
  4. package/dist/core/analytics.d.ts.map +1 -0
  5. package/dist/core/analytics.js +334 -0
  6. package/dist/core/analytics.js.map +1 -0
  7. package/dist/core/errors.d.ts +94 -0
  8. package/dist/core/errors.d.ts.map +1 -0
  9. package/dist/core/errors.js +420 -0
  10. package/dist/core/errors.js.map +1 -0
  11. package/dist/core/logger.d.ts +28 -0
  12. package/dist/core/logger.d.ts.map +1 -0
  13. package/dist/core/logger.js +36 -0
  14. package/dist/core/logger.js.map +1 -0
  15. package/dist/core/logging.d.ts +12 -0
  16. package/dist/core/logging.d.ts.map +1 -0
  17. package/dist/core/logging.js +33 -0
  18. package/dist/core/logging.js.map +1 -0
  19. package/dist/core/privacy.d.ts +53 -0
  20. package/dist/core/privacy.d.ts.map +1 -0
  21. package/dist/core/privacy.js +94 -0
  22. package/dist/core/privacy.js.map +1 -0
  23. package/dist/core/queue.d.ts +59 -0
  24. package/dist/core/queue.d.ts.map +1 -0
  25. package/dist/core/queue.js +263 -0
  26. package/dist/core/queue.js.map +1 -0
  27. package/dist/core/session.d.ts +90 -0
  28. package/dist/core/session.d.ts.map +1 -0
  29. package/dist/core/session.js +246 -0
  30. package/dist/core/session.js.map +1 -0
  31. package/dist/core/storage.d.ts +64 -0
  32. package/dist/core/storage.d.ts.map +1 -0
  33. package/dist/core/storage.js +242 -0
  34. package/dist/core/storage.js.map +1 -0
  35. package/dist/core/types.d.ts +298 -0
  36. package/dist/core/types.d.ts.map +1 -0
  37. package/dist/core/types.js +34 -0
  38. package/dist/core/types.js.map +1 -0
  39. package/dist/core/validation.d.ts +11 -0
  40. package/dist/core/validation.d.ts.map +1 -0
  41. package/dist/core/validation.js +82 -0
  42. package/dist/core/validation.js.map +1 -0
  43. package/dist/core/version.d.ts +2 -0
  44. package/dist/core/version.d.ts.map +1 -0
  45. package/dist/core/version.js +4 -0
  46. package/dist/core/version.js.map +1 -0
  47. package/dist/index.d.ts +45 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +41 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/next/analytics.d.ts +59 -0
  52. package/dist/next/analytics.d.ts.map +1 -0
  53. package/dist/next/analytics.js +87 -0
  54. package/dist/next/analytics.js.map +1 -0
  55. package/dist/next.d.ts +46 -0
  56. package/dist/next.d.ts.map +1 -0
  57. package/dist/next.js +44 -0
  58. package/dist/next.js.map +1 -0
  59. package/dist/react/analytics.d.ts +51 -0
  60. package/dist/react/analytics.d.ts.map +1 -0
  61. package/dist/react/analytics.js +63 -0
  62. package/dist/react/analytics.js.map +1 -0
  63. package/dist/react/bug-report-widget.d.ts +21 -0
  64. package/dist/react/bug-report-widget.d.ts.map +1 -0
  65. package/dist/react/bug-report-widget.js +34 -0
  66. package/dist/react/bug-report-widget.js.map +1 -0
  67. package/dist/react/hooks.d.ts +141 -0
  68. package/dist/react/hooks.d.ts.map +1 -0
  69. package/dist/react/hooks.js +186 -0
  70. package/dist/react/hooks.js.map +1 -0
  71. package/dist/react.d.ts +42 -0
  72. package/dist/react.d.ts.map +1 -0
  73. package/dist/react.js +39 -0
  74. package/dist/react.js.map +1 -0
  75. package/dist/widget/bug-report.d.ts +16 -0
  76. package/dist/widget/bug-report.d.ts.map +1 -0
  77. package/dist/widget/bug-report.js +416 -0
  78. package/dist/widget/bug-report.js.map +1 -0
  79. package/package.json +107 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Thisbefine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,403 @@
1
+ # @thisbefine/analytics
2
+
3
+ > Know what's happening in your app. Fix it before your users complain.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@thisbefine/analytics.svg)](https://www.npmjs.com/package/@thisbefine/analytics)
6
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/@thisbefine/analytics)](https://bundlephobia.com/package/@thisbefine/analytics)
7
+ [![license](https://img.shields.io/npm/l/@thisbefine/analytics.svg)](https://github.com/thisbefine/analytics/blob/main/LICENSE)
8
+
9
+ Lightweight analytics, error tracking, and logging for indie SaaS. Everything is fine. Your app is on fire? That's fine. Now you'll at least know about it.
10
+
11
+ **~5KB gzipped** | **TypeScript-first** | **Privacy-respecting** | **Zero dependencies**
12
+
13
+ ## Why Thisbefine?
14
+
15
+ - **Built for indie hackers** - No enterprise complexity, just what you need
16
+ - **All-in-one** - Analytics + errors + logs in one tiny package
17
+ - **Privacy-first** - Respects DNT and GPC by default (we're not the bad guys)
18
+ - **Framework support** - First-class React and Next.js integration
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @thisbefine/analytics
24
+ # or
25
+ pnpm add @thisbefine/analytics
26
+ # or
27
+ yarn add @thisbefine/analytics
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ### Next.js (App Router)
33
+
34
+ ```tsx
35
+ // app/layout.tsx
36
+ import { Analytics } from '@thisbefine/analytics/next';
37
+
38
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
39
+ return (
40
+ <html lang="en">
41
+ <body>
42
+ {children}
43
+ <Analytics />
44
+ </body>
45
+ </html>
46
+ );
47
+ }
48
+ ```
49
+
50
+ Zero config. Reads `NEXT_PUBLIC_TBF_API_KEY` from your environment. Automatic page view tracking on route changes.
51
+
52
+ ```tsx
53
+ // components/signup-button.tsx
54
+ 'use client';
55
+ import { useTrack } from '@thisbefine/analytics/next';
56
+
57
+ export function SignupButton() {
58
+ const track = useTrack('signup_clicked');
59
+
60
+ return (
61
+ <button onClick={() => track({ location: 'header' })}>
62
+ Sign Up
63
+ </button>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### React
69
+
70
+ ```tsx
71
+ // main.tsx
72
+ import { Analytics } from '@thisbefine/analytics/react';
73
+
74
+ ReactDOM.createRoot(document.getElementById('root')!).render(
75
+ <>
76
+ <App />
77
+ <Analytics apiKey={import.meta.env.VITE_TBF_API_KEY} />
78
+ </>
79
+ );
80
+ ```
81
+
82
+ ### Vanilla JavaScript
83
+
84
+ ```typescript
85
+ import { createAnalytics } from '@thisbefine/analytics';
86
+
87
+ const analytics = createAnalytics({
88
+ apiKey: 'tbf_xxx',
89
+ });
90
+
91
+ // Track events
92
+ analytics.track('button_clicked', { buttonId: 'signup' });
93
+
94
+ // Identify users
95
+ analytics.identify('user_123', { email: 'user@example.com', plan: 'pro' });
96
+
97
+ // Track page views
98
+ analytics.page('/dashboard');
99
+ ```
100
+
101
+ ## Features
102
+
103
+ ### Analytics
104
+
105
+ Track what matters. Skip the vanity metrics.
106
+
107
+ ```typescript
108
+ // Track custom events
109
+ analytics.track('subscription_upgraded', {
110
+ plan: 'pro',
111
+ mrr: 29,
112
+ previous_plan: 'free',
113
+ });
114
+
115
+ // Identify users after login
116
+ analytics.identify('user_123', {
117
+ email: 'user@example.com',
118
+ name: 'Jane Doe',
119
+ plan: 'pro',
120
+ });
121
+
122
+ // Associate users with companies/accounts
123
+ analytics.group('company_456', {
124
+ name: 'Acme Inc',
125
+ plan: 'enterprise',
126
+ mrr: 499,
127
+ });
128
+ ```
129
+
130
+ ### Error Tracking
131
+
132
+ Catch errors before users catch you slipping.
133
+
134
+ ```typescript
135
+ // Automatic error capture (enabled by default)
136
+ // Or capture manually:
137
+ analytics.captureException(error, {
138
+ component: 'PaymentForm',
139
+ userId: 'user_123',
140
+ });
141
+
142
+ // Add breadcrumbs for context
143
+ analytics.addBreadcrumb({
144
+ category: 'ui',
145
+ message: 'User clicked checkout button',
146
+ });
147
+
148
+ // Log error messages
149
+ analytics.captureMessage('Payment failed', 'error', {
150
+ orderId: 'order_789',
151
+ });
152
+ ```
153
+
154
+ ### Structured Logging
155
+
156
+ Logs that actually help you debug.
157
+
158
+ ```typescript
159
+ analytics.log('User completed onboarding', 'info', {
160
+ step: 3,
161
+ duration: 45000,
162
+ });
163
+
164
+ // Log levels: debug, info, warn, error, fatal
165
+ analytics.log('Cache miss for user preferences', 'debug', {
166
+ userId: 'user_123',
167
+ });
168
+ ```
169
+
170
+ ### Privacy Controls
171
+
172
+ Because being creepy is bad for business.
173
+
174
+ ```typescript
175
+ // SDK respects DNT and GPC by default
176
+ // Users can also opt out programmatically:
177
+ analytics.optOut();
178
+
179
+ // Check status
180
+ if (analytics.isOptedOut()) {
181
+ console.log('User has opted out');
182
+ }
183
+
184
+ // Opt back in
185
+ analytics.optIn();
186
+ ```
187
+
188
+ ## React Hooks
189
+
190
+ All hooks are available from both `@thisbefine/analytics/react` and `@thisbefine/analytics/next`.
191
+
192
+ ### useTrack
193
+
194
+ Memoized track function for a specific event.
195
+
196
+ ```tsx
197
+ const trackClick = useTrack('button_clicked');
198
+
199
+ <button onClick={() => trackClick({ buttonId: 'cta' })}>
200
+ Click me
201
+ </button>
202
+ ```
203
+
204
+ ### useIdentify
205
+
206
+ Identify users after authentication.
207
+
208
+ ```tsx
209
+ const identify = useIdentify();
210
+
211
+ // After login
212
+ identify(user.id, {
213
+ email: user.email,
214
+ plan: user.plan,
215
+ });
216
+ ```
217
+
218
+ ### useGroup
219
+
220
+ Associate users with accounts/companies.
221
+
222
+ ```tsx
223
+ const group = useGroup();
224
+
225
+ // After selecting workspace
226
+ group(workspace.id, {
227
+ name: workspace.name,
228
+ plan: workspace.plan,
229
+ });
230
+ ```
231
+
232
+ ### useAnalytics
233
+
234
+ Full analytics instance for advanced usage.
235
+
236
+ ```tsx
237
+ const analytics = useAnalytics();
238
+
239
+ analytics.track('custom_event', { foo: 'bar' });
240
+ analytics.captureException(error);
241
+ analytics.log('Something happened', 'info');
242
+ ```
243
+
244
+ ### useReset
245
+
246
+ Reset session on logout.
247
+
248
+ ```tsx
249
+ const reset = useReset();
250
+
251
+ const handleLogout = () => {
252
+ reset();
253
+ router.push('/login');
254
+ };
255
+ ```
256
+
257
+ ### useCaptureException
258
+
259
+ Capture errors in components.
260
+
261
+ ```tsx
262
+ const captureException = useCaptureException();
263
+
264
+ try {
265
+ await riskyOperation();
266
+ } catch (error) {
267
+ captureException(error as Error, { component: 'RiskyComponent' });
268
+ }
269
+ ```
270
+
271
+ ### useLog
272
+
273
+ Structured logging from components.
274
+
275
+ ```tsx
276
+ const log = useLog();
277
+
278
+ log('User viewed pricing page', 'info', { referrer: document.referrer });
279
+ ```
280
+
281
+ ## Configuration
282
+
283
+ ```typescript
284
+ import { createAnalytics } from '@thisbefine/analytics';
285
+
286
+ const analytics = createAnalytics({
287
+ // Required
288
+ apiKey: 'tbf_xxx',
289
+
290
+ // Optional
291
+ host: 'https://thisbefine.com', // API endpoint
292
+ debug: false, // Console logging
293
+ flushAt: 20, // Batch size before sending
294
+ flushInterval: 10000, // Ms between flushes
295
+ sessionTimeout: 1800000, // 30 min session timeout
296
+ cookieDomain: '.yourdomain.com', // Cross-subdomain tracking
297
+ respectDNT: true, // Honor Do Not Track
298
+ maxRetries: 3, // Retry failed requests
299
+
300
+ // Error tracking config
301
+ errors: {
302
+ enabled: true,
303
+ captureUnhandled: true,
304
+ captureConsoleErrors: true,
305
+ },
306
+ });
307
+ ```
308
+
309
+ ### Analytics Component Props
310
+
311
+ ```tsx
312
+ <Analytics
313
+ apiKey="tbf_xxx" // Optional if NEXT_PUBLIC_TBF_API_KEY is set
314
+ host="http://localhost:3000" // For local development
315
+ debug={true} // Enable console logging
316
+ trackPageviews={true} // Auto track page views (default: true)
317
+ config={{ // Additional config options
318
+ flushAt: 10,
319
+ sessionTimeout: 60 * 60 * 1000,
320
+ }}
321
+ />
322
+ ```
323
+
324
+ ## API Reference
325
+
326
+ ### Core Methods
327
+
328
+ | Method | Description |
329
+ |--------|-------------|
330
+ | `track(event, properties?)` | Track a custom event |
331
+ | `identify(userId, traits?)` | Identify a user |
332
+ | `page(name?, properties?)` | Track a page view |
333
+ | `group(accountId, traits?)` | Associate user with account |
334
+ | `reset()` | Clear user data (call on logout) |
335
+ | `flush()` | Force send queued events |
336
+ | `optOut()` | Disable tracking |
337
+ | `optIn()` | Re-enable tracking |
338
+ | `isOptedOut()` | Check opt-out status |
339
+ | `getUser()` | Get current user state |
340
+
341
+ ### Error Tracking Methods
342
+
343
+ | Method | Description |
344
+ |--------|-------------|
345
+ | `captureException(error, context?)` | Capture an error |
346
+ | `captureMessage(message, level?, context?)` | Capture a message |
347
+ | `addBreadcrumb(breadcrumb)` | Add context for errors |
348
+
349
+ ### Logging Method
350
+
351
+ | Method | Description |
352
+ |--------|-------------|
353
+ | `log(message, level, metadata?)` | Send structured log |
354
+
355
+ Log levels: `debug` | `info` | `warn` | `error` | `fatal`
356
+
357
+ ## Storage
358
+
359
+ The SDK stores data locally with the `tif_` prefix:
360
+
361
+ | Key | Purpose | Persistence |
362
+ |-----|---------|-------------|
363
+ | `tif_anonymous_id` | Anonymous user ID | Permanent |
364
+ | `tif_user_id` | Identified user ID | Until reset |
365
+ | `tif_session_id` | Current session | 30 min timeout |
366
+ | `tif_user_traits` | User properties | Until reset |
367
+ | `tif_opt_out` | Opt-out flag | Permanent |
368
+
369
+ Storage fallback: localStorage > sessionStorage > cookies > memory
370
+
371
+ ## TypeScript
372
+
373
+ Full type definitions included:
374
+
375
+ ```typescript
376
+ import type {
377
+ Analytics,
378
+ AnalyticsConfig,
379
+ UserState,
380
+ UserTraits,
381
+ AccountTraits,
382
+ } from '@thisbefine/analytics';
383
+ ```
384
+
385
+ ## Bundle Size
386
+
387
+ | Import | Size (gzipped) |
388
+ |--------|----------------|
389
+ | `@thisbefine/analytics` | ~5KB |
390
+ | `@thisbefine/analytics/react` | +2KB |
391
+ | `@thisbefine/analytics/next` | +1KB |
392
+
393
+ ## Browser Support
394
+
395
+ Chrome 80+ | Firefox 75+ | Safari 13+ | Edge 80+
396
+
397
+ ## Contributing
398
+
399
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines.
400
+
401
+ ## License
402
+
403
+ MIT
@@ -0,0 +1,123 @@
1
+ import type { LogLevel } from "./logging";
2
+ import type { AccountTraits, Analytics, AnalyticsConfig, UserState, UserTraits } from "./types";
3
+ /**
4
+ * Main Analytics class - the primary entry point for the SDK
5
+ *
6
+ * Usage:
7
+ * ```typescript
8
+ * const analytics = createAnalytics({ apiKey: 'tbf_xxx' });
9
+ *
10
+ * analytics.track('button_clicked', { buttonId: 'signup' });
11
+ * analytics.identify('user_123', { email: 'user@example.com' });
12
+ * analytics.page('/dashboard');
13
+ * ```
14
+ */
15
+ export declare class AnalyticsImpl implements Analytics {
16
+ private config;
17
+ private storage;
18
+ private session;
19
+ private queue;
20
+ private privacy;
21
+ private errorCapture;
22
+ private initialized;
23
+ private logger;
24
+ constructor(config: AnalyticsConfig);
25
+ /**
26
+ * Resolve configuration with defaults
27
+ */
28
+ private resolveConfig;
29
+ /**
30
+ * Track a custom event
31
+ */
32
+ track(event: string, properties?: Record<string, unknown>): void;
33
+ /**
34
+ * Identify a user with traits
35
+ */
36
+ identify(userId: string, traits?: UserTraits): void;
37
+ /**
38
+ * Track a page view
39
+ */
40
+ page(name?: string, properties?: Record<string, unknown>): void;
41
+ /**
42
+ * Associate the current user with an account/company
43
+ */
44
+ group(accountId: string, traits?: AccountTraits): void;
45
+ /**
46
+ * Capture an exception and send to error tracking
47
+ */
48
+ captureException(error: Error, context?: Record<string, unknown>): void;
49
+ /**
50
+ * Capture a message as an error event
51
+ */
52
+ captureMessage(message: string, level?: "error" | "fatal" | "warning", context?: Record<string, unknown>): void;
53
+ /**
54
+ * Add a breadcrumb for error context
55
+ */
56
+ addBreadcrumb(breadcrumb: {
57
+ type: "click" | "navigation" | "network" | "console" | "custom";
58
+ message: string;
59
+ data?: Record<string, unknown>;
60
+ }): void;
61
+ /**
62
+ * Send a structured log event
63
+ */
64
+ log(message: string, level: LogLevel, metadata?: Record<string, unknown>): void;
65
+ /**
66
+ * Reset the current user session (call on logout)
67
+ */
68
+ reset(): void;
69
+ /**
70
+ * Manually flush the event queue
71
+ */
72
+ flush(): Promise<void>;
73
+ /**
74
+ * Opt out of tracking
75
+ */
76
+ optOut(): void;
77
+ /**
78
+ * Opt back in to tracking
79
+ */
80
+ optIn(): void;
81
+ /**
82
+ * Check if user has opted out
83
+ */
84
+ isOptedOut(): boolean;
85
+ /**
86
+ * Get current user state
87
+ */
88
+ getUser(): UserState;
89
+ /**
90
+ * Check if tracking should be allowed
91
+ */
92
+ private shouldTrack;
93
+ /**
94
+ * Build event context
95
+ */
96
+ private getContext;
97
+ }
98
+ /**
99
+ * Create a new Analytics instance
100
+ *
101
+ * @param config - Analytics configuration
102
+ * @returns Analytics instance
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const analytics = createAnalytics({
107
+ * apiKey: 'tbf_xxx',
108
+ * debug: process.env.NODE_ENV === 'development',
109
+ * });
110
+ *
111
+ * analytics.track('signup_completed', { plan: 'pro' });
112
+ * ```
113
+ */
114
+ export declare const createAnalytics: (config: AnalyticsConfig) => Analytics;
115
+ /**
116
+ * Get or create a global analytics instance (for script tag usage)
117
+ */
118
+ export declare const getAnalytics: () => Analytics | null;
119
+ /**
120
+ * Initialize the global analytics instance
121
+ */
122
+ export declare const initAnalytics: (config: AnalyticsConfig) => Analytics;
123
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/core/analytics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAM1C,OAAO,KAAK,EACX,aAAa,EACb,SAAS,EACT,eAAe,EAOf,SAAS,EACT,UAAU,EACV,MAAM,SAAS,CAAC;AASjB;;;;;;;;;;;GAWG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC9C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,eAAe;IAkCnC;;OAEG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA+BhE;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAmCnD;;OAEG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA+B/D;;OAEG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI;IAmCtD;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAKvE;;OAEG;IACH,cAAc,CACb,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,EACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI;IAKP;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE;QACzB,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;QAChE,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC/B,GAAG,IAAI;IAIR;;OAEG;IACH,GAAG,CACF,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,QAAQ,EACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI;IAKP;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,OAAO,IAAI,SAAS;IAIpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAanB;;OAEG;IACH,OAAO,CAAC,UAAU;CA8BlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,eAAe,KAAG,SAEzD,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,YAAY,QAAO,SAAS,GAAG,IAE3C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,eAAe,KAAG,SAQvD,CAAC"}