@journium/js 1.0.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 +366 -0
- package/dist/autocapture.d.ts +37 -0
- package/dist/autocapture.d.ts.map +1 -0
- package/dist/client.d.ts +23 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/index.cjs +1425 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +1408 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +1431 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/journium.d.ts +29 -0
- package/dist/journium.d.ts.map +1 -0
- package/dist/pageview.d.ts +13 -0
- package/dist/pageview.d.ts.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# @journium/js
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/@journium%2Fjs)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
7
|
+
**The official Journium JavaScript SDK for web browsers**
|
|
8
|
+
|
|
9
|
+
Track events, pageviews, and user interactions with ease. Perfect for SPAs, vanilla JavaScript apps, and any web application.
|
|
10
|
+
|
|
11
|
+
## 🚀 Quick Start
|
|
12
|
+
|
|
13
|
+
### Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @journium/js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Basic Usage
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
import { init } from '@journium/js';
|
|
23
|
+
|
|
24
|
+
// Initialize Journium
|
|
25
|
+
const journium = init({
|
|
26
|
+
token: 'your-journium-token',
|
|
27
|
+
apiHost: 'https://your-journium-instance.com'
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Track events
|
|
31
|
+
journium.track('button_clicked', {
|
|
32
|
+
button_name: 'signup',
|
|
33
|
+
page: 'homepage'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Track pageviews (optional - can be automatic)
|
|
37
|
+
journium.capturePageview();
|
|
38
|
+
|
|
39
|
+
// Start auto-capture - automatically enabled when calling startAutoCapture()
|
|
40
|
+
// Autocapture is enabled by default, but you need to start it:
|
|
41
|
+
journium.startAutoCapture();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 📖 API Reference
|
|
45
|
+
|
|
46
|
+
### Initialization
|
|
47
|
+
|
|
48
|
+
#### `init(config: JourniumConfig)`
|
|
49
|
+
|
|
50
|
+
Initialize the Journium SDK with your configuration.
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const journium = init({
|
|
54
|
+
token: 'your-journium-token', // Required: Your project token
|
|
55
|
+
apiHost: 'https://api.journium.com', // Required: Your API endpoint
|
|
56
|
+
debug: false, // Optional: Enable debug logs
|
|
57
|
+
flushAt: 20, // Optional: Flush after N events
|
|
58
|
+
flushInterval: 10000, // Optional: Flush interval (ms)
|
|
59
|
+
autocapture: true, // Optional: (default: true) - set false to disable
|
|
60
|
+
sessionTimeout: 1800000 // Optional: Session timeout (30m)
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Event Tracking
|
|
65
|
+
|
|
66
|
+
#### `journium.track(eventName, properties?)`
|
|
67
|
+
|
|
68
|
+
Track custom events with optional properties.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
// Simple event
|
|
72
|
+
journium.track('feature_used');
|
|
73
|
+
|
|
74
|
+
// Event with properties
|
|
75
|
+
journium.track('purchase_completed', {
|
|
76
|
+
product_id: 'prod_123',
|
|
77
|
+
amount: 29.99,
|
|
78
|
+
currency: 'USD',
|
|
79
|
+
category: 'digital',
|
|
80
|
+
plan: 'premium'
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// User action with context
|
|
84
|
+
journium.track('video_played', {
|
|
85
|
+
video_id: 'intro-2024',
|
|
86
|
+
video_length: 120,
|
|
87
|
+
quality: '1080p',
|
|
88
|
+
autoplay: false
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### `journium.identify(distinctId, attributes?)`
|
|
93
|
+
|
|
94
|
+
Identify a user when they log in or sign up. This method should be used instead of tracking user login as a custom event.
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
// When user logs in or signs up
|
|
98
|
+
journium.identify('user_12345', {
|
|
99
|
+
name: 'John Doe',
|
|
100
|
+
email: 'john@example.com'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Minimal identification (just user ID)
|
|
104
|
+
journium.identify('user_67890');
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### `journium.reset()`
|
|
108
|
+
|
|
109
|
+
Reset user identity when they log out. This generates a new anonymous distinct ID and should be called on user logout.
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// When user logs out
|
|
113
|
+
journium.reset();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### `journium.capturePageview(properties?)`
|
|
117
|
+
|
|
118
|
+
Manually capture pageview events.
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
// Simple pageview
|
|
122
|
+
journium.capturePageview();
|
|
123
|
+
|
|
124
|
+
// Pageview with custom properties
|
|
125
|
+
journium.capturePageview({
|
|
126
|
+
section: 'pricing',
|
|
127
|
+
experiment_variant: 'v2',
|
|
128
|
+
user_plan: 'free'
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Auto-Capture
|
|
133
|
+
|
|
134
|
+
#### `journium.startAutoCapture()` / `journium.stopAutoCapture()`
|
|
135
|
+
|
|
136
|
+
Control automatic event capture for clicks, pageviews, and form interactions.
|
|
137
|
+
|
|
138
|
+
**Note:** Autocapture is enabled by default. You can disable it entirely with `autocapture: false` in your config, or control it programmatically:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
// Start capturing events automatically (autocapture is enabled by default)
|
|
142
|
+
journium.startAutoCapture();
|
|
143
|
+
|
|
144
|
+
// Stop automatic capture
|
|
145
|
+
journium.stopAutoCapture();
|
|
146
|
+
|
|
147
|
+
// Or disable entirely in configuration:
|
|
148
|
+
const journium = init({
|
|
149
|
+
token: 'your-token',
|
|
150
|
+
apiHost: 'your-api.com',
|
|
151
|
+
autocapture: false // Disables all autocapture functionality
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Configure what gets auto-captured:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
const journium = init({
|
|
159
|
+
token: 'your-token',
|
|
160
|
+
apiHost: 'https://your-api.com',
|
|
161
|
+
autocapture: {
|
|
162
|
+
captureClicks: true, // Track click events
|
|
163
|
+
captureFormSubmits: true, // Track form submissions
|
|
164
|
+
captureFormChanges: false, // Track form field changes
|
|
165
|
+
captureTextSelection: false, // Track text selections
|
|
166
|
+
captureContentText: true, // Include element text
|
|
167
|
+
ignoreClasses: ['no-track'], // CSS classes to ignore
|
|
168
|
+
ignoreElements: ['input[type="password"]'] // Elements to ignore
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Data Management
|
|
174
|
+
|
|
175
|
+
#### `journium.flush()`
|
|
176
|
+
|
|
177
|
+
Manually send queued events to the server.
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
// Send all pending events immediately
|
|
181
|
+
await journium.flush();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### `journium.destroy()`
|
|
185
|
+
|
|
186
|
+
Clean up the SDK and send any remaining events.
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
// Cleanup before page unload
|
|
190
|
+
journium.destroy();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## 🏗️ Event Properties
|
|
194
|
+
|
|
195
|
+
### Automatic Properties
|
|
196
|
+
|
|
197
|
+
Journium automatically includes these properties with every event:
|
|
198
|
+
|
|
199
|
+
- `$device_id` - Unique device identifier (persistent across user sessions)
|
|
200
|
+
- `$session_id` - Current session ID
|
|
201
|
+
- `distinct_id` - User identifier (anonymous until `identify()` is called)
|
|
202
|
+
- `$is_identified` - Whether the user has been identified (true/false)
|
|
203
|
+
- `$current_url` - Current page URL
|
|
204
|
+
- `$pathname` - URL pathname
|
|
205
|
+
- `$browser` - Browser name (Chrome, Firefox, etc.)
|
|
206
|
+
- `$os` - Operating system (Windows, macOS, etc.)
|
|
207
|
+
- `$device_type` - Device type (desktop, mobile, tablet)
|
|
208
|
+
- `$lib_version` - SDK version
|
|
209
|
+
- `$platform` - Always "web"
|
|
210
|
+
|
|
211
|
+
### Custom Properties
|
|
212
|
+
|
|
213
|
+
Add any custom properties to track additional context:
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
journium.track('feature_used', {
|
|
217
|
+
// Your custom properties
|
|
218
|
+
feature_name: 'dark_mode',
|
|
219
|
+
user_plan: 'premium',
|
|
220
|
+
user_role: 'admin',
|
|
221
|
+
experiment_group: 'control',
|
|
222
|
+
|
|
223
|
+
// Nested objects work too
|
|
224
|
+
user_preferences: {
|
|
225
|
+
theme: 'dark',
|
|
226
|
+
language: 'en',
|
|
227
|
+
timezone: 'UTC'
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 🔧 Configuration Options
|
|
233
|
+
|
|
234
|
+
### Required Configuration
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
{
|
|
238
|
+
token: 'your-journium-token', // Your project token from Journium
|
|
239
|
+
apiHost: 'https://api.journium.com' // Your Journium API endpoint
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Optional Configuration
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
{
|
|
247
|
+
debug: false, // Enable console logging
|
|
248
|
+
flushAt: 20, // Send events after N events queued
|
|
249
|
+
flushInterval: 10000, // Send events every N milliseconds
|
|
250
|
+
sessionTimeout: 1800000, // Session timeout (30 minutes)
|
|
251
|
+
autocapture: true // Default: true - set false to disable auto-capture
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Advanced Auto-Capture Configuration
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
{
|
|
259
|
+
autocapture: {
|
|
260
|
+
captureClicks: true, // Capture click events
|
|
261
|
+
captureFormSubmits: true, // Capture form submissions
|
|
262
|
+
captureFormChanges: false, // Capture form field changes
|
|
263
|
+
captureTextSelection: false, // Capture text selection events
|
|
264
|
+
captureContentText: true, // Include element text content
|
|
265
|
+
ignoreClasses: [ // CSS classes to ignore
|
|
266
|
+
'no-track',
|
|
267
|
+
'sensitive-data',
|
|
268
|
+
'admin-only'
|
|
269
|
+
],
|
|
270
|
+
ignoreElements: [ // CSS selectors to ignore
|
|
271
|
+
'input[type="password"]',
|
|
272
|
+
'.credit-card-input',
|
|
273
|
+
'[data-private]'
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 🔒 Privacy & Security
|
|
280
|
+
|
|
281
|
+
Journium is designed with privacy in mind:
|
|
282
|
+
|
|
283
|
+
- **No PII by default** - We don't automatically collect personally identifiable information
|
|
284
|
+
- **Configurable tracking** - Exclude sensitive elements and data
|
|
285
|
+
- **Secure transmission** - All data sent over HTTPS
|
|
286
|
+
- **Session-based** - Automatic session management without persistent user tracking
|
|
287
|
+
|
|
288
|
+
### Excluding Sensitive Data
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
// Method 1: CSS classes
|
|
292
|
+
<button class="signup-btn no-track">Sign Up</button>
|
|
293
|
+
|
|
294
|
+
// Method 2: Configuration
|
|
295
|
+
const journium = init({
|
|
296
|
+
token: 'your-token',
|
|
297
|
+
apiHost: 'your-api.com',
|
|
298
|
+
autocapture: {
|
|
299
|
+
ignoreClasses: ['no-track', 'sensitive'],
|
|
300
|
+
ignoreElements: ['input[type="password"]', '.credit-card']
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## 🌐 Browser Support
|
|
306
|
+
|
|
307
|
+
- ✅ **Chrome** 60+
|
|
308
|
+
- ✅ **Firefox** 55+
|
|
309
|
+
- ✅ **Safari** 12+
|
|
310
|
+
- ✅ **Edge** 79+
|
|
311
|
+
- ✅ **Mobile browsers** (iOS Safari, Chrome Mobile)
|
|
312
|
+
|
|
313
|
+
## 📝 TypeScript Support
|
|
314
|
+
|
|
315
|
+
Full TypeScript support with complete type definitions:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { init, JourniumConfig, Journium } from '@journium/js';
|
|
319
|
+
|
|
320
|
+
const config: JourniumConfig = {
|
|
321
|
+
token: 'your-token',
|
|
322
|
+
apiHost: 'https://api.journium.com',
|
|
323
|
+
debug: true
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const journium: Journium = init(config);
|
|
327
|
+
|
|
328
|
+
// Type-safe event tracking
|
|
329
|
+
journium.track('user_action', {
|
|
330
|
+
action_type: 'click',
|
|
331
|
+
element_id: 'signup-button',
|
|
332
|
+
timestamp: new Date().toISOString()
|
|
333
|
+
});
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## 🔗 Related Packages
|
|
337
|
+
|
|
338
|
+
Part of the Journium JavaScript SDK ecosystem:
|
|
339
|
+
|
|
340
|
+
- **[@journium/react](https://npmjs.com/package/@journium/react)** - React integration with hooks and providers
|
|
341
|
+
- **[@journium/nextjs](https://npmjs.com/package/@journium/nextjs)** - Next.js integration with SSR support
|
|
342
|
+
- **[@journium/node](https://npmjs.com/package/@journium/node)** - Node.js server-side tracking
|
|
343
|
+
- **[@journium/core](https://npmjs.com/package/@journium/core)** - Core utilities and types
|
|
344
|
+
|
|
345
|
+
## 📖 Documentation
|
|
346
|
+
|
|
347
|
+
For complete documentation, guides, and examples:
|
|
348
|
+
|
|
349
|
+
- **[Documentation](https://docs.journium.app)** - Complete guides and API reference
|
|
350
|
+
- **[Getting Started](https://docs.journium.app/getting-started)** - Quick setup guide
|
|
351
|
+
- **[Examples](https://docs.journium.app/examples)** - Code examples and patterns
|
|
352
|
+
|
|
353
|
+
## 🤝 Contributing
|
|
354
|
+
|
|
355
|
+
We welcome contributions! Please see our [Contributing Guide](https://github.com/journium/journium-js/blob/main/CONTRIBUTING.md).
|
|
356
|
+
|
|
357
|
+
## 📄 License
|
|
358
|
+
|
|
359
|
+
MIT License - see [LICENSE](https://github.com/journium/journium-js/blob/main/LICENSE) file for details.
|
|
360
|
+
|
|
361
|
+
## 🆘 Support
|
|
362
|
+
|
|
363
|
+
- **📚 Docs**: [docs.journium.app](https://docs.journium.app)
|
|
364
|
+
- **🐛 Issues**: [GitHub Issues](https://github.com/journium/journium-js/issues)
|
|
365
|
+
- **💬 Discussions**: [GitHub Discussions](https://github.com/journium/journium-js/discussions)
|
|
366
|
+
- **📧 Email**: support@journium.com
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { JourniumClient } from './client';
|
|
2
|
+
export interface AutocaptureConfig {
|
|
3
|
+
captureClicks?: boolean;
|
|
4
|
+
captureFormSubmits?: boolean;
|
|
5
|
+
captureFormChanges?: boolean;
|
|
6
|
+
captureTextSelection?: boolean;
|
|
7
|
+
ignoreClasses?: string[];
|
|
8
|
+
ignoreElements?: string[];
|
|
9
|
+
captureContentText?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface AutocaptureEvent {
|
|
12
|
+
event: string;
|
|
13
|
+
properties: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
export declare class AutocaptureTracker {
|
|
16
|
+
private client;
|
|
17
|
+
private config;
|
|
18
|
+
private listeners;
|
|
19
|
+
private isActive;
|
|
20
|
+
constructor(client: JourniumClient, config?: AutocaptureConfig);
|
|
21
|
+
start(): void;
|
|
22
|
+
stop(): void;
|
|
23
|
+
private addClickListener;
|
|
24
|
+
private addFormSubmitListener;
|
|
25
|
+
private addFormChangeListener;
|
|
26
|
+
private addTextSelectionListener;
|
|
27
|
+
private shouldIgnoreElement;
|
|
28
|
+
private isFormElement;
|
|
29
|
+
private getElementProperties;
|
|
30
|
+
private getFormProperties;
|
|
31
|
+
private getInputProperties;
|
|
32
|
+
private getElementType;
|
|
33
|
+
private getElementText;
|
|
34
|
+
private getElementsChain;
|
|
35
|
+
private isSafeInputType;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=autocapture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocapture.d.ts","sourceRoot":"","sources":["../src/autocapture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,cAAc,EAAE,MAAM,GAAE,iBAAsB;IAclE,KAAK,IAAI,IAAI;IAwBb,IAAI,IAAI,IAAI;IAcZ,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,oBAAoB;IAiE5B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,gBAAgB;IAqFxB,OAAO,CAAC,eAAe;CAKxB"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { JourniumConfig } from '@journium/core';
|
|
2
|
+
export declare class JourniumClient {
|
|
3
|
+
private config;
|
|
4
|
+
private queue;
|
|
5
|
+
private flushTimer;
|
|
6
|
+
private initialized;
|
|
7
|
+
private identityManager;
|
|
8
|
+
private configStorageKey;
|
|
9
|
+
constructor(config: JourniumConfig);
|
|
10
|
+
private loadCachedConfig;
|
|
11
|
+
private saveCachedConfig;
|
|
12
|
+
private initializeSync;
|
|
13
|
+
private fetchRemoteConfigAsync;
|
|
14
|
+
private fetchAndCacheRemoteConfig;
|
|
15
|
+
private startFlushTimer;
|
|
16
|
+
private sendEvents;
|
|
17
|
+
identify(distinctId: string, attributes?: Record<string, any>): void;
|
|
18
|
+
reset(): void;
|
|
19
|
+
track(event: string, properties?: Record<string, any>): void;
|
|
20
|
+
flush(): Promise<void>;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAgH,MAAM,gBAAgB,CAAC;AAE7K,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,gBAAgB,CAAU;gBAEtB,MAAM,EAAE,cAAc;IAyBlC,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,cAAc;YAoDR,sBAAsB;YAOtB,yBAAyB;IA0CvC,OAAO,CAAC,eAAe;YAWT,UAAU;IA8BxB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,IAAI;IAyBxE,KAAK,IAAI,IAAI;IAiBb,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAAG,IAAI;IA4C1D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB5B,OAAO,IAAI,IAAI;CAOhB"}
|