@grainql/analytics-web 2.4.0 → 2.5.3
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/dist/cjs/index.d.ts +29 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interaction-tracking.d.ts +74 -0
- package/dist/cjs/interaction-tracking.d.ts.map +1 -0
- package/dist/cjs/interaction-tracking.js +292 -0
- package/dist/cjs/interaction-tracking.js.map +1 -0
- package/dist/cjs/section-tracking.d.ts +101 -0
- package/dist/cjs/section-tracking.d.ts.map +1 -0
- package/dist/cjs/section-tracking.js +455 -0
- package/dist/cjs/section-tracking.js.map +1 -0
- package/dist/cjs/types/auto-tracking.d.ts +55 -0
- package/dist/cjs/types/auto-tracking.d.ts.map +1 -0
- package/dist/cjs/types/auto-tracking.js +6 -0
- package/dist/cjs/types/auto-tracking.js.map +1 -0
- package/dist/esm/index.d.ts +29 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interaction-tracking.d.ts +74 -0
- package/dist/esm/interaction-tracking.d.ts.map +1 -0
- package/dist/esm/interaction-tracking.js +288 -0
- package/dist/esm/interaction-tracking.js.map +1 -0
- package/dist/esm/section-tracking.d.ts +101 -0
- package/dist/esm/section-tracking.d.ts.map +1 -0
- package/dist/esm/section-tracking.js +451 -0
- package/dist/esm/section-tracking.js.map +1 -0
- package/dist/esm/types/auto-tracking.d.ts +55 -0
- package/dist/esm/types/auto-tracking.d.ts.map +1 -0
- package/dist/esm/types/auto-tracking.js +5 -0
- package/dist/esm/types/auto-tracking.js.map +1 -0
- package/dist/index.d.ts +29 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.global.dev.js +821 -3
- package/dist/index.global.dev.js.map +4 -4
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +4 -4
- package/dist/index.js +149 -4
- package/dist/index.mjs +116 -4
- package/dist/interaction-tracking.d.ts +74 -0
- package/dist/interaction-tracking.d.ts.map +1 -0
- package/dist/interaction-tracking.js +292 -0
- package/dist/section-tracking.d.ts +101 -0
- package/dist/section-tracking.d.ts.map +1 -0
- package/dist/section-tracking.js +455 -0
- package/dist/types/auto-tracking.d.ts +55 -0
- package/dist/types/auto-tracking.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interaction Tracking Manager for Grain Analytics
|
|
4
|
+
* Automatically attaches click and focus listeners to detected interactive elements
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.InteractionTrackingManager = void 0;
|
|
8
|
+
class InteractionTrackingManager {
|
|
9
|
+
constructor(tracker, interactions, config = {}) {
|
|
10
|
+
this.isDestroyed = false;
|
|
11
|
+
this.attachedListeners = new Map();
|
|
12
|
+
this.xpathCache = new Map();
|
|
13
|
+
this.mutationObserver = null;
|
|
14
|
+
this.mutationDebounceTimer = null;
|
|
15
|
+
this.tracker = tracker;
|
|
16
|
+
this.interactions = interactions;
|
|
17
|
+
this.config = {
|
|
18
|
+
debug: config.debug ?? false,
|
|
19
|
+
enableMutationObserver: config.enableMutationObserver ?? true,
|
|
20
|
+
mutationDebounceDelay: config.mutationDebounceDelay ?? 500,
|
|
21
|
+
};
|
|
22
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
23
|
+
// Attach listeners after DOM is ready
|
|
24
|
+
if (document.readyState === 'loading') {
|
|
25
|
+
document.addEventListener('DOMContentLoaded', () => this.attachAllListeners());
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// DOM already loaded
|
|
29
|
+
setTimeout(() => this.attachAllListeners(), 0);
|
|
30
|
+
}
|
|
31
|
+
// Setup mutation observer for dynamic content
|
|
32
|
+
if (this.config.enableMutationObserver) {
|
|
33
|
+
this.setupMutationObserver();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Attach listeners to all configured interactions
|
|
39
|
+
*/
|
|
40
|
+
attachAllListeners() {
|
|
41
|
+
if (this.isDestroyed)
|
|
42
|
+
return;
|
|
43
|
+
this.log('Attaching interaction listeners for', this.interactions.length, 'interactions');
|
|
44
|
+
for (const interaction of this.interactions) {
|
|
45
|
+
this.attachInteractionListener(interaction);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Attach listener to a specific interaction
|
|
50
|
+
*/
|
|
51
|
+
attachInteractionListener(interaction) {
|
|
52
|
+
if (this.isDestroyed)
|
|
53
|
+
return;
|
|
54
|
+
const element = this.findElementByXPath(interaction.selector);
|
|
55
|
+
if (!element) {
|
|
56
|
+
this.log('Element not found for interaction:', interaction.eventName, 'selector:', interaction.selector);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Check if we already attached listeners to this element for this interaction
|
|
60
|
+
if (this.attachedListeners.has(element)) {
|
|
61
|
+
this.log('Listeners already attached for element:', element);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const handlers = [];
|
|
65
|
+
// Click handler
|
|
66
|
+
const clickHandler = (event) => this.handleInteractionClick(interaction, event);
|
|
67
|
+
element.addEventListener('click', clickHandler, { passive: true });
|
|
68
|
+
handlers.push({ event: 'click', handler: clickHandler });
|
|
69
|
+
// Focus handler (for form inputs)
|
|
70
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
|
|
71
|
+
const focusHandler = (event) => this.handleInteractionFocus(interaction, event);
|
|
72
|
+
element.addEventListener('focus', focusHandler, { passive: true });
|
|
73
|
+
handlers.push({ event: 'focus', handler: focusHandler });
|
|
74
|
+
}
|
|
75
|
+
this.attachedListeners.set(element, handlers);
|
|
76
|
+
this.log('Attached listeners to element for:', interaction.eventName);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Handle click event on interaction
|
|
80
|
+
*/
|
|
81
|
+
handleInteractionClick(interaction, event) {
|
|
82
|
+
if (this.isDestroyed)
|
|
83
|
+
return;
|
|
84
|
+
if (!this.tracker.hasConsent('analytics'))
|
|
85
|
+
return;
|
|
86
|
+
const element = event.target;
|
|
87
|
+
// Check if this is a navigation link (has href attribute)
|
|
88
|
+
const isNavigationLink = element instanceof HTMLAnchorElement && element.href;
|
|
89
|
+
const eventProperties = {
|
|
90
|
+
interaction_type: 'click',
|
|
91
|
+
interaction_label: interaction.label,
|
|
92
|
+
interaction_description: interaction.description,
|
|
93
|
+
interaction_priority: interaction.priority,
|
|
94
|
+
element_tag: element.tagName?.toLowerCase(),
|
|
95
|
+
element_text: element.textContent?.trim().substring(0, 100),
|
|
96
|
+
element_id: element.id || undefined,
|
|
97
|
+
element_class: element.className || undefined,
|
|
98
|
+
...(isNavigationLink && { href: element.href }),
|
|
99
|
+
timestamp: Date.now(),
|
|
100
|
+
};
|
|
101
|
+
// If it's a navigation link, flush immediately to ensure event is sent before navigation
|
|
102
|
+
if (isNavigationLink) {
|
|
103
|
+
// Use flush option to send immediately - handle promise if returned
|
|
104
|
+
const result = this.tracker.track(interaction.eventName, eventProperties, { flush: true });
|
|
105
|
+
if (result instanceof Promise) {
|
|
106
|
+
result.catch((error) => {
|
|
107
|
+
// Log error but don't block navigation
|
|
108
|
+
this.log('Failed to track navigation click:', error);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.tracker.track(interaction.eventName, eventProperties);
|
|
114
|
+
}
|
|
115
|
+
this.log('Tracked click interaction:', interaction.eventName);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Handle focus event on interaction (for form fields)
|
|
119
|
+
*/
|
|
120
|
+
handleInteractionFocus(interaction, event) {
|
|
121
|
+
if (this.isDestroyed)
|
|
122
|
+
return;
|
|
123
|
+
if (!this.tracker.hasConsent('analytics'))
|
|
124
|
+
return;
|
|
125
|
+
const element = event.target;
|
|
126
|
+
this.tracker.track(interaction.eventName, {
|
|
127
|
+
interaction_type: 'focus',
|
|
128
|
+
interaction_label: interaction.label,
|
|
129
|
+
interaction_description: interaction.description,
|
|
130
|
+
interaction_priority: interaction.priority,
|
|
131
|
+
element_tag: element.tagName?.toLowerCase(),
|
|
132
|
+
element_id: element.id || undefined,
|
|
133
|
+
element_class: element.className || undefined,
|
|
134
|
+
timestamp: Date.now(),
|
|
135
|
+
});
|
|
136
|
+
this.log('Tracked focus interaction:', interaction.eventName);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Find element by XPath selector
|
|
140
|
+
*/
|
|
141
|
+
findElementByXPath(xpath) {
|
|
142
|
+
// Check cache first
|
|
143
|
+
if (this.xpathCache.has(xpath)) {
|
|
144
|
+
const cached = this.xpathCache.get(xpath);
|
|
145
|
+
// Verify element is still in DOM
|
|
146
|
+
if (cached && document.contains(cached)) {
|
|
147
|
+
return cached;
|
|
148
|
+
}
|
|
149
|
+
// Clear invalid cache entry
|
|
150
|
+
this.xpathCache.delete(xpath);
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
// Strip the xpath= prefix if present (from Stagehand selectors)
|
|
154
|
+
let cleanXpath = xpath;
|
|
155
|
+
if (xpath.startsWith('xpath=')) {
|
|
156
|
+
cleanXpath = xpath.substring(6); // Remove 'xpath=' prefix
|
|
157
|
+
}
|
|
158
|
+
const result = document.evaluate(cleanXpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
|
159
|
+
const element = result.singleNodeValue;
|
|
160
|
+
// Cache the result (use original xpath as key)
|
|
161
|
+
if (element) {
|
|
162
|
+
this.xpathCache.set(xpath, element);
|
|
163
|
+
}
|
|
164
|
+
return element;
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
this.log('Error evaluating XPath:', xpath, error);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Setup mutation observer to handle dynamic content
|
|
173
|
+
*/
|
|
174
|
+
setupMutationObserver() {
|
|
175
|
+
if (typeof MutationObserver === 'undefined') {
|
|
176
|
+
this.log('MutationObserver not supported');
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
this.mutationObserver = new MutationObserver((mutations) => {
|
|
180
|
+
// Debounce the re-attachment
|
|
181
|
+
if (this.mutationDebounceTimer !== null) {
|
|
182
|
+
clearTimeout(this.mutationDebounceTimer);
|
|
183
|
+
}
|
|
184
|
+
this.mutationDebounceTimer = window.setTimeout(() => {
|
|
185
|
+
this.handleMutations(mutations);
|
|
186
|
+
this.mutationDebounceTimer = null;
|
|
187
|
+
}, this.config.mutationDebounceDelay);
|
|
188
|
+
});
|
|
189
|
+
this.mutationObserver.observe(document.body, {
|
|
190
|
+
childList: true,
|
|
191
|
+
subtree: true,
|
|
192
|
+
});
|
|
193
|
+
this.log('Mutation observer setup');
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Handle DOM mutations
|
|
197
|
+
*/
|
|
198
|
+
handleMutations(mutations) {
|
|
199
|
+
if (this.isDestroyed)
|
|
200
|
+
return;
|
|
201
|
+
// Clear XPath cache on mutations
|
|
202
|
+
this.xpathCache.clear();
|
|
203
|
+
// Check if any of our tracked elements were removed
|
|
204
|
+
const removedElements = new Set();
|
|
205
|
+
for (const mutation of mutations) {
|
|
206
|
+
mutation.removedNodes.forEach((node) => {
|
|
207
|
+
if (node instanceof Element) {
|
|
208
|
+
removedElements.add(node);
|
|
209
|
+
// Also check for child elements we were tracking
|
|
210
|
+
this.attachedListeners.forEach((handlers, element) => {
|
|
211
|
+
if (node.contains(element)) {
|
|
212
|
+
removedElements.add(element);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
// Clean up removed elements
|
|
219
|
+
removedElements.forEach((element) => {
|
|
220
|
+
this.detachListeners(element);
|
|
221
|
+
});
|
|
222
|
+
// Try to re-attach listeners for any interactions that might now be available
|
|
223
|
+
this.attachAllListeners();
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Detach listeners from an element
|
|
227
|
+
*/
|
|
228
|
+
detachListeners(element) {
|
|
229
|
+
const handlers = this.attachedListeners.get(element);
|
|
230
|
+
if (!handlers)
|
|
231
|
+
return;
|
|
232
|
+
handlers.forEach(({ event, handler }) => {
|
|
233
|
+
element.removeEventListener(event, handler);
|
|
234
|
+
});
|
|
235
|
+
this.attachedListeners.delete(element);
|
|
236
|
+
this.log('Detached listeners from element');
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Log debug messages
|
|
240
|
+
*/
|
|
241
|
+
log(...args) {
|
|
242
|
+
if (this.config.debug) {
|
|
243
|
+
console.log('[InteractionTracking]', ...args);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Update interactions configuration
|
|
248
|
+
*/
|
|
249
|
+
updateInteractions(interactions) {
|
|
250
|
+
if (this.isDestroyed)
|
|
251
|
+
return;
|
|
252
|
+
this.log('Updating interactions configuration');
|
|
253
|
+
// Detach all existing listeners
|
|
254
|
+
this.attachedListeners.forEach((handlers, element) => {
|
|
255
|
+
this.detachListeners(element);
|
|
256
|
+
});
|
|
257
|
+
// Clear cache
|
|
258
|
+
this.xpathCache.clear();
|
|
259
|
+
// Update configuration
|
|
260
|
+
this.interactions = interactions;
|
|
261
|
+
// Reattach listeners
|
|
262
|
+
this.attachAllListeners();
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Cleanup and destroy
|
|
266
|
+
*/
|
|
267
|
+
destroy() {
|
|
268
|
+
if (this.isDestroyed)
|
|
269
|
+
return;
|
|
270
|
+
this.log('Destroying interaction tracking manager');
|
|
271
|
+
this.isDestroyed = true;
|
|
272
|
+
// Clear debounce timer
|
|
273
|
+
if (this.mutationDebounceTimer !== null) {
|
|
274
|
+
clearTimeout(this.mutationDebounceTimer);
|
|
275
|
+
this.mutationDebounceTimer = null;
|
|
276
|
+
}
|
|
277
|
+
// Disconnect mutation observer
|
|
278
|
+
if (this.mutationObserver) {
|
|
279
|
+
this.mutationObserver.disconnect();
|
|
280
|
+
this.mutationObserver = null;
|
|
281
|
+
}
|
|
282
|
+
// Detach all listeners
|
|
283
|
+
this.attachedListeners.forEach((handlers, element) => {
|
|
284
|
+
this.detachListeners(element);
|
|
285
|
+
});
|
|
286
|
+
// Clear caches
|
|
287
|
+
this.attachedListeners.clear();
|
|
288
|
+
this.xpathCache.clear();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
exports.InteractionTrackingManager = InteractionTrackingManager;
|
|
292
|
+
//# sourceMappingURL=interaction-tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction-tracking.js","sourceRoot":"","sources":["../../src/interaction-tracking.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section Tracking Manager for Grain Analytics
|
|
3
|
+
* Intelligent scroll tracking with viewport metrics, visible sections, and engagement analysis
|
|
4
|
+
*/
|
|
5
|
+
import type { SectionConfig, SectionTrackingOptions } from './types/auto-tracking';
|
|
6
|
+
export interface SectionTracker {
|
|
7
|
+
trackSystemEvent(eventName: string, properties: Record<string, unknown>): void;
|
|
8
|
+
hasConsent(category: 'analytics' | 'marketing' | 'functional'): boolean;
|
|
9
|
+
log(...args: unknown[]): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class SectionTrackingManager {
|
|
12
|
+
private tracker;
|
|
13
|
+
private sections;
|
|
14
|
+
private options;
|
|
15
|
+
private isDestroyed;
|
|
16
|
+
private sectionStates;
|
|
17
|
+
private intersectionObserver;
|
|
18
|
+
private xpathCache;
|
|
19
|
+
private lastScrollPosition;
|
|
20
|
+
private lastScrollTime;
|
|
21
|
+
private scrollVelocity;
|
|
22
|
+
private scrollDebounceTimer;
|
|
23
|
+
private pendingEvents;
|
|
24
|
+
private batchTimer;
|
|
25
|
+
private sectionTimers;
|
|
26
|
+
private readonly SPLIT_DURATION;
|
|
27
|
+
constructor(tracker: SectionTracker, sections: SectionConfig[], options?: Partial<SectionTrackingOptions>);
|
|
28
|
+
/**
|
|
29
|
+
* Initialize section tracking
|
|
30
|
+
*/
|
|
31
|
+
private initialize;
|
|
32
|
+
/**
|
|
33
|
+
* Setup IntersectionObserver for section visibility
|
|
34
|
+
*/
|
|
35
|
+
private setupIntersectionObserver;
|
|
36
|
+
/**
|
|
37
|
+
* Setup scroll listener for velocity calculation
|
|
38
|
+
*/
|
|
39
|
+
private setupScrollListener;
|
|
40
|
+
/**
|
|
41
|
+
* Initialize sections and start observing
|
|
42
|
+
*/
|
|
43
|
+
private initializeSections;
|
|
44
|
+
/**
|
|
45
|
+
* Handle intersection observer entry
|
|
46
|
+
*/
|
|
47
|
+
private handleIntersection;
|
|
48
|
+
/**
|
|
49
|
+
* Handle section entry (became visible)
|
|
50
|
+
*/
|
|
51
|
+
private handleSectionEntry;
|
|
52
|
+
/**
|
|
53
|
+
* Start periodic tracking for a section (sends events every 3 seconds)
|
|
54
|
+
*/
|
|
55
|
+
private startPeriodicTracking;
|
|
56
|
+
/**
|
|
57
|
+
* Stop periodic tracking for a section
|
|
58
|
+
*/
|
|
59
|
+
private stopPeriodicTracking;
|
|
60
|
+
/**
|
|
61
|
+
* Handle section exit (became invisible)
|
|
62
|
+
*/
|
|
63
|
+
private handleSectionExit;
|
|
64
|
+
/**
|
|
65
|
+
* Update scroll velocity
|
|
66
|
+
*/
|
|
67
|
+
private updateScrollVelocity;
|
|
68
|
+
/**
|
|
69
|
+
* Calculate current scroll depth as percentage
|
|
70
|
+
*/
|
|
71
|
+
private calculateScrollDepth;
|
|
72
|
+
/**
|
|
73
|
+
* Determine if section view should be tracked (sanitization)
|
|
74
|
+
*/
|
|
75
|
+
private shouldTrackSection;
|
|
76
|
+
/**
|
|
77
|
+
* Queue section view for batching
|
|
78
|
+
*/
|
|
79
|
+
private queueSectionView;
|
|
80
|
+
/**
|
|
81
|
+
* Flush pending section view events
|
|
82
|
+
*/
|
|
83
|
+
private flushPendingEvents;
|
|
84
|
+
/**
|
|
85
|
+
* Find element by XPath selector
|
|
86
|
+
*/
|
|
87
|
+
private findElementByXPath;
|
|
88
|
+
/**
|
|
89
|
+
* Log debug messages
|
|
90
|
+
*/
|
|
91
|
+
private log;
|
|
92
|
+
/**
|
|
93
|
+
* Update sections configuration
|
|
94
|
+
*/
|
|
95
|
+
updateSections(sections: SectionConfig[]): void;
|
|
96
|
+
/**
|
|
97
|
+
* Cleanup and destroy
|
|
98
|
+
*/
|
|
99
|
+
destroy(): void;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=section-tracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-tracking.d.ts","sourceRoot":"","sources":["../../src/section-tracking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAmB,sBAAsB,EAAwB,MAAM,uBAAuB,CAAC;AAE1H,MAAM,WAAW,cAAc;IAC7B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/E,UAAU,CAAC,QAAQ,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,OAAO,CAAC;IACxE,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAC/B;AAWD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,aAAa,CAAgD;IACrE,OAAO,CAAC,oBAAoB,CAAqC;IACjE,OAAO,CAAC,UAAU,CAA0C;IAG5D,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,mBAAmB,CAAuB;IAGlD,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,UAAU,CAAuB;IAGzC,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;gBAGrC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,GAAE,OAAO,CAAC,sBAAsB,CAAM;IAgB/C;;OAEG;IACH,OAAO,CAAC,UAAU;IAelB;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAqBjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkC1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA2D7B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAQ5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuCzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAuC1B;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI;IAsB/C;;OAEG;IACH,OAAO,IAAI,IAAI;CAsChB"}
|