@liteforge/router 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.
@@ -0,0 +1,475 @@
1
+ import { effect } from '@liteforge/core';
2
+ import { use, pushContext, popContext, isComponentFactory } from '@liteforge/runtime';
3
+ import { isPathActive } from './route-matcher.js';
4
+ import { isLazyComponent, getLazyDelay, getLazyLoading, getLazyError } from './lazy.js';
5
+ /**
6
+ * RouterOutlet renders the component for the current matched route.
7
+ *
8
+ * For nested routes, each RouterOutlet tracks its depth and renders
9
+ * the appropriate level of the route match chain.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // Basic usage
14
+ * const outlet = RouterOutlet();
15
+ *
16
+ * // With fallback for no match
17
+ * const outlet = RouterOutlet({ fallback: () => document.createTextNode('Not Found') });
18
+ * ```
19
+ */
20
+ export function RouterOutlet(config = {}) {
21
+ const { fallback } = config;
22
+ // Get router from context
23
+ let router;
24
+ try {
25
+ router = use('router');
26
+ }
27
+ catch {
28
+ throw new Error('RouterOutlet requires a router in context. Make sure to use createApp with a router.');
29
+ }
30
+ // Get current outlet depth (default 0 for top-level)
31
+ let depth;
32
+ try {
33
+ depth = use('router:outlet-depth') ?? 0;
34
+ }
35
+ catch {
36
+ depth = 0;
37
+ }
38
+ // Create a container for the outlet
39
+ const container = document.createDocumentFragment();
40
+ // Placeholder comment node for positioning
41
+ const placeholder = document.createComment(`router-outlet:${depth}`);
42
+ container.appendChild(placeholder);
43
+ // Track current mounted component/node
44
+ let currentInstance = null;
45
+ let currentNode = null;
46
+ let parentNode = null;
47
+ // Track current route to avoid remounting same component on child navigation
48
+ // We compare routes (not components) because compiled routes are stable references
49
+ let currentRoute = null;
50
+ // Cleanup function for effect
51
+ let cleanupEffect = null;
52
+ // Navigation ID for race condition handling
53
+ let navigationId = 0;
54
+ // Delay timer ID
55
+ let delayTimerId = null;
56
+ /**
57
+ * Clear delay timer if active
58
+ */
59
+ function clearDelayTimer() {
60
+ if (delayTimerId !== null) {
61
+ clearTimeout(delayTimerId);
62
+ delayTimerId = null;
63
+ }
64
+ }
65
+ /**
66
+ * Unmount current content
67
+ * Note: Does NOT reset currentComponent - that's managed by renderComponent()
68
+ */
69
+ function unmountCurrent() {
70
+ clearDelayTimer();
71
+ if (currentInstance) {
72
+ currentInstance.unmount();
73
+ currentInstance = null;
74
+ }
75
+ if (currentNode && currentNode.parentNode) {
76
+ currentNode.parentNode.removeChild(currentNode);
77
+ currentNode = null;
78
+ }
79
+ }
80
+ /**
81
+ * Mount a node at the outlet position
82
+ */
83
+ function mountNode(node) {
84
+ parentNode = placeholder.parentNode;
85
+ if (!parentNode)
86
+ return;
87
+ // Remove current node if any (without full unmount)
88
+ if (currentNode && currentNode.parentNode) {
89
+ currentNode.parentNode.removeChild(currentNode);
90
+ }
91
+ parentNode.insertBefore(node, placeholder.nextSibling);
92
+ currentNode = node;
93
+ }
94
+ /**
95
+ * Render a sync route component
96
+ */
97
+ function renderSyncComponent(component, props) {
98
+ unmountCurrent();
99
+ parentNode = placeholder.parentNode;
100
+ if (!parentNode)
101
+ return;
102
+ // Check if it's a ComponentFactory
103
+ if (isComponentFactory(component)) {
104
+ pushContext({ 'router:outlet-depth': depth + 1 });
105
+ try {
106
+ currentInstance = component(props);
107
+ const tempContainer = document.createElement('div');
108
+ currentInstance.mount(tempContainer);
109
+ const mountedNode = tempContainer.firstChild;
110
+ if (mountedNode) {
111
+ parentNode.insertBefore(mountedNode, placeholder.nextSibling);
112
+ currentNode = mountedNode;
113
+ }
114
+ }
115
+ finally {
116
+ popContext();
117
+ }
118
+ }
119
+ else if (typeof component === 'function') {
120
+ pushContext({ 'router:outlet-depth': depth + 1 });
121
+ try {
122
+ // Call with props - some components expect them
123
+ const result = component(props);
124
+ currentNode = result;
125
+ parentNode.insertBefore(currentNode, placeholder.nextSibling);
126
+ }
127
+ finally {
128
+ popContext();
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * Render a route component (sync or lazy)
134
+ */
135
+ function renderComponent(route, component, props) {
136
+ // Same route as currently rendered → don't remount
137
+ // This is critical for nested routes: when navigating /dashboard → /dashboard/users,
138
+ // the parent layout (depth 0) stays mounted, only the child outlet (depth 1) updates
139
+ // We compare routes (not components) because compiled routes are stable references
140
+ if (route === currentRoute) {
141
+ return;
142
+ }
143
+ currentRoute = route;
144
+ // Increment navigation ID to invalidate any pending loads
145
+ // This must happen AFTER the route check, so same-route calls don't invalidate
146
+ navigationId++;
147
+ const thisNavigationId = navigationId;
148
+ // Check if it's a lazy component
149
+ if (isLazyComponent(component)) {
150
+ // Check if already loaded - use SYNCHRONOUS getLoaded() to avoid microtask race
151
+ const loadedComponent = component.getLoaded();
152
+ if (loadedComponent) {
153
+ // Already loaded - render SYNCHRONOUSLY (no .then(), no microtask)
154
+ renderSyncComponent(loadedComponent, props);
155
+ return;
156
+ }
157
+ // Not loaded yet - handle lazy loading with delay
158
+ handleLazyComponent(component, props, thisNavigationId);
159
+ return;
160
+ }
161
+ // Check if it's a ComponentFactory (from createComponent)
162
+ if (isComponentFactory(component)) {
163
+ renderSyncComponent(component, props);
164
+ return;
165
+ }
166
+ // It's a plain function (either sync or lazy loader without our wrapper)
167
+ if (typeof component === 'function') {
168
+ pushContext({ 'router:outlet-depth': depth + 1 });
169
+ try {
170
+ // Call with props - component may expect them
171
+ const result = component(props);
172
+ if (result instanceof Promise) {
173
+ popContext();
174
+ // Plain lazy loader - handle without delay features
175
+ handlePlainLazyComponent(result, props, thisNavigationId);
176
+ }
177
+ else {
178
+ unmountCurrent();
179
+ parentNode = placeholder.parentNode;
180
+ if (parentNode) {
181
+ currentNode = result;
182
+ parentNode.insertBefore(currentNode, placeholder.nextSibling);
183
+ }
184
+ popContext();
185
+ }
186
+ }
187
+ catch (error) {
188
+ popContext();
189
+ throw error;
190
+ }
191
+ }
192
+ }
193
+ /**
194
+ * Handle lazy-loaded component with delay behavior
195
+ */
196
+ function handleLazyComponent(lazyComponent, props, navId) {
197
+ const delay = getLazyDelay(lazyComponent);
198
+ const loadingFn = getLazyLoading(lazyComponent);
199
+ const errorFn = getLazyError(lazyComponent);
200
+ // Set up delay timer for showing loading state
201
+ if (delay > 0 && loadingFn) {
202
+ clearDelayTimer();
203
+ delayTimerId = setTimeout(() => {
204
+ if (navigationId !== navId)
205
+ return; // Stale navigation
206
+ // Show loading state after delay
207
+ const loadingNode = loadingFn();
208
+ mountNode(loadingNode);
209
+ }, delay);
210
+ }
211
+ else if (delay === 0 && loadingFn) {
212
+ // Show loading immediately (delay = 0)
213
+ unmountCurrent();
214
+ parentNode = placeholder.parentNode;
215
+ if (parentNode) {
216
+ const loadingNode = loadingFn();
217
+ parentNode.insertBefore(loadingNode, placeholder.nextSibling);
218
+ currentNode = loadingNode;
219
+ }
220
+ }
221
+ // Start loading the component
222
+ lazyComponent().then(module => {
223
+ clearDelayTimer();
224
+ if (navigationId !== navId)
225
+ return; // Stale navigation
226
+ const loadedComponent = 'default' in module ? module.default : module;
227
+ renderSyncComponent(loadedComponent, props);
228
+ }).catch((error) => {
229
+ clearDelayTimer();
230
+ if (navigationId !== navId)
231
+ return; // Stale navigation
232
+ const err = error instanceof Error ? error : new Error(String(error));
233
+ console.error('Failed to load lazy component:', err);
234
+ if (errorFn) {
235
+ // Show error state with retry
236
+ const retry = () => {
237
+ lazyComponent.reset();
238
+ handleLazyComponent(lazyComponent, props, navigationId);
239
+ };
240
+ unmountCurrent();
241
+ parentNode = placeholder.parentNode;
242
+ if (parentNode) {
243
+ const errorNode = errorFn(err, retry);
244
+ parentNode.insertBefore(errorNode, placeholder.nextSibling);
245
+ currentNode = errorNode;
246
+ }
247
+ }
248
+ });
249
+ }
250
+ /**
251
+ * Handle plain lazy component (without our wrapper)
252
+ */
253
+ async function handlePlainLazyComponent(promise, props, navId) {
254
+ try {
255
+ const module = await promise;
256
+ if (navigationId !== navId)
257
+ return; // Stale navigation
258
+ const component = 'default' in module ? module.default : module;
259
+ renderSyncComponent(component, props);
260
+ }
261
+ catch (error) {
262
+ if (navigationId !== navId)
263
+ return; // Stale navigation
264
+ console.error('Failed to load lazy component:', error);
265
+ }
266
+ }
267
+ /**
268
+ * Render fallback content
269
+ */
270
+ function renderFallback() {
271
+ unmountCurrent();
272
+ if (fallback) {
273
+ parentNode = placeholder.parentNode;
274
+ if (parentNode) {
275
+ currentNode = fallback();
276
+ parentNode.insertBefore(currentNode, placeholder.nextSibling);
277
+ }
278
+ }
279
+ }
280
+ // Set up effect to watch route changes
281
+ // We need to defer this until the placeholder is in the DOM
282
+ const originalPlaceholder = placeholder;
283
+ // Use MutationObserver to detect when we're added to DOM
284
+ if (typeof MutationObserver !== 'undefined') {
285
+ const observer = new MutationObserver(() => {
286
+ if (originalPlaceholder.parentNode) {
287
+ observer.disconnect();
288
+ setupRouteWatcher();
289
+ }
290
+ });
291
+ // Observe the document for changes
292
+ observer.observe(document, { childList: true, subtree: true });
293
+ // Also check immediately in case we're already in DOM
294
+ if (originalPlaceholder.parentNode) {
295
+ observer.disconnect();
296
+ // Use setTimeout to ensure context is properly set up
297
+ setTimeout(setupRouteWatcher, 0);
298
+ }
299
+ }
300
+ else {
301
+ // Fallback for environments without MutationObserver
302
+ setTimeout(setupRouteWatcher, 0);
303
+ }
304
+ function setupRouteWatcher() {
305
+ cleanupEffect = effect(() => {
306
+ const matched = router.matched();
307
+ const preloadedData = router.preloadedData();
308
+ const params = router.params();
309
+ const query = router.query();
310
+ // Get the match at our depth level
311
+ const matchAtDepth = matched[depth];
312
+ if (!matchAtDepth) {
313
+ // No match at this depth
314
+ renderFallback();
315
+ return;
316
+ }
317
+ const { route } = matchAtDepth;
318
+ const component = route.component;
319
+ if (!component) {
320
+ // Route has no component (might be redirect-only)
321
+ renderFallback();
322
+ return;
323
+ }
324
+ // Build props for the route component
325
+ const componentProps = {
326
+ params,
327
+ query,
328
+ preloaded: preloadedData,
329
+ };
330
+ renderComponent(route, component, componentProps);
331
+ });
332
+ }
333
+ // Return a node that cleans up when removed
334
+ // We wrap the placeholder in a custom behavior
335
+ const result = placeholder;
336
+ // Store cleanup function on the node for later access
337
+ result.__cleanup = () => {
338
+ if (cleanupEffect) {
339
+ cleanupEffect();
340
+ cleanupEffect = null;
341
+ }
342
+ unmountCurrent();
343
+ };
344
+ return result;
345
+ }
346
+ /**
347
+ * Link creates an anchor element with client-side navigation.
348
+ *
349
+ * @example
350
+ * ```ts
351
+ * // Basic link
352
+ * const link = Link({ href: '/about', children: 'About Us' });
353
+ *
354
+ * // With active class
355
+ * const navLink = Link({
356
+ * href: '/users',
357
+ * children: 'Users',
358
+ * activeClass: 'nav-active',
359
+ * exactActiveClass: 'nav-exact',
360
+ * });
361
+ * ```
362
+ */
363
+ export function Link(config) {
364
+ const { href, children, activeClass = 'active', exactActiveClass = 'exact-active', exact = false, class: className, replace = false, target, attrs = {}, preload, } = config;
365
+ // Get router from context
366
+ let router;
367
+ try {
368
+ router = use('router');
369
+ }
370
+ catch {
371
+ throw new Error('Link requires a router in context. Make sure to use createApp with a router.');
372
+ }
373
+ // Create anchor element
374
+ const anchor = document.createElement('a');
375
+ anchor.href = href;
376
+ // Set children
377
+ if (typeof children === 'string') {
378
+ anchor.textContent = children;
379
+ }
380
+ else {
381
+ anchor.appendChild(children);
382
+ }
383
+ // Set static class
384
+ if (className) {
385
+ anchor.className = className;
386
+ }
387
+ // Set target
388
+ if (target) {
389
+ anchor.target = target;
390
+ }
391
+ // Set additional attributes
392
+ for (const [key, value] of Object.entries(attrs)) {
393
+ anchor.setAttribute(key, value);
394
+ }
395
+ // Track if preload has been triggered (only do it once)
396
+ let preloadTriggered = false;
397
+ // Handle preload on hover
398
+ if (preload) {
399
+ anchor.addEventListener('mouseenter', () => {
400
+ if (preloadTriggered)
401
+ return;
402
+ preloadTriggered = true;
403
+ // If preload is a LazyComponent, prefetch it directly
404
+ if (preload !== true && isLazyComponent(preload)) {
405
+ preload.prefetch();
406
+ return;
407
+ }
408
+ // If preload is true, try to find the route's lazy component
409
+ const resolved = router.resolve(href);
410
+ const routeComponent = resolved.route?.component;
411
+ if (routeComponent && isLazyComponent(routeComponent)) {
412
+ routeComponent.prefetch();
413
+ }
414
+ });
415
+ }
416
+ // Handle click for client-side navigation
417
+ anchor.addEventListener('click', (event) => {
418
+ // Don't handle if modifier keys are pressed (allow new tab)
419
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
420
+ return;
421
+ }
422
+ // Don't handle if target is _blank
423
+ if (anchor.target === '_blank') {
424
+ return;
425
+ }
426
+ // Don't handle external links
427
+ if (anchor.origin !== window.location.origin) {
428
+ return;
429
+ }
430
+ // Prevent default browser navigation
431
+ event.preventDefault();
432
+ // Navigate using router
433
+ if (replace) {
434
+ router.replace(href);
435
+ }
436
+ else {
437
+ router.navigate(href);
438
+ }
439
+ });
440
+ // Set up effect to manage active classes
441
+ const disposeEffect = effect(() => {
442
+ const currentPath = router.path();
443
+ // Check for exact match
444
+ const isExactActive = isPathActive(currentPath, href, true);
445
+ // Check for active match (exact if `exact` prop is true, otherwise prefix match)
446
+ const isActive = exact
447
+ ? isExactActive
448
+ : isPathActive(currentPath, href, false);
449
+ // Manage exact active class
450
+ if (isExactActive) {
451
+ anchor.classList.add(exactActiveClass);
452
+ }
453
+ else {
454
+ anchor.classList.remove(exactActiveClass);
455
+ }
456
+ // Manage active class
457
+ if (isActive) {
458
+ anchor.classList.add(activeClass);
459
+ }
460
+ else {
461
+ anchor.classList.remove(activeClass);
462
+ }
463
+ });
464
+ // Store cleanup function on the element
465
+ anchor.__cleanup = disposeEffect;
466
+ return anchor;
467
+ }
468
+ // =============================================================================
469
+ // NavLink (Convenience Alias)
470
+ // =============================================================================
471
+ /**
472
+ * NavLink is an alias for Link with navigation-focused defaults.
473
+ */
474
+ export const NavLink = Link;
475
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import type { RouteGuard, GuardFunction, GuardContext, GuardResult, CompiledRoute, NavigationTarget } from './types.js';
2
+ /**
3
+ * Define a named route guard
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * const authGuard = defineGuard('auth', ({ to, from, use }) => {
8
+ * const auth = use('auth');
9
+ * if (!auth.isAuthenticated()) {
10
+ * return `/login?redirect=${encodeURIComponent(to.path)}`;
11
+ * }
12
+ * return true;
13
+ * });
14
+ *
15
+ * // Parameterized guard
16
+ * const roleGuard = defineGuard('role', ({ use, param }) => {
17
+ * return use('auth').hasRole(param) || '/unauthorized';
18
+ * });
19
+ * ```
20
+ */
21
+ export declare function defineGuard(name: string, handler: GuardFunction): RouteGuard;
22
+ /**
23
+ * Guard registry for managing named guards
24
+ */
25
+ export declare class GuardRegistry {
26
+ private guards;
27
+ /**
28
+ * Register a guard
29
+ */
30
+ register(guard: RouteGuard): void;
31
+ /**
32
+ * Register multiple guards
33
+ */
34
+ registerAll(guards: RouteGuard[]): void;
35
+ /**
36
+ * Get a guard by name
37
+ */
38
+ get(name: string): RouteGuard | undefined;
39
+ /**
40
+ * Check if a guard exists
41
+ */
42
+ has(name: string): boolean;
43
+ /**
44
+ * Unregister a guard
45
+ */
46
+ unregister(name: string): boolean;
47
+ /**
48
+ * Get all guard names
49
+ */
50
+ names(): string[];
51
+ /**
52
+ * Clear all guards
53
+ */
54
+ clear(): void;
55
+ /**
56
+ * Get the internal map (for route compilation)
57
+ */
58
+ getMap(): Map<string, RouteGuard>;
59
+ }
60
+ /**
61
+ * Normalize guard result to a consistent format
62
+ */
63
+ export declare function normalizeGuardResult(result: GuardResult): {
64
+ allowed: boolean;
65
+ redirect?: NavigationTarget;
66
+ };
67
+ /**
68
+ * Run all guards for a route match
69
+ * Guards are run in order; first failing guard stops execution
70
+ */
71
+ export declare function runGuards(guards: RouteGuard[], context: Omit<GuardContext, 'param'>): Promise<{
72
+ allowed: boolean;
73
+ redirect?: NavigationTarget;
74
+ }>;
75
+ /**
76
+ * Resolve guards from guard specification using the registry
77
+ * This is called at navigation time to support dynamic guard registration
78
+ */
79
+ export declare function resolveGuardsFromSpec(guardSpec: CompiledRoute['guardSpec'], registry: GuardRegistry): RouteGuard[];
80
+ /**
81
+ * Collect all guards for a matched route chain
82
+ * (including parent route guards for nested routes)
83
+ * Resolves string guards from the registry at runtime
84
+ */
85
+ export declare function collectRouteGuards(route: CompiledRoute, registry?: GuardRegistry): RouteGuard[];
86
+ /**
87
+ * Create a simple authentication guard
88
+ */
89
+ export declare function createAuthGuard(isAuthenticated: () => boolean, loginPath?: string): RouteGuard;
90
+ /**
91
+ * Create a role-based guard
92
+ * Usage: guard: 'role:admin' or guard: 'role:editor'
93
+ */
94
+ export declare function createRoleGuard(hasRole: (role: string) => boolean, unauthorizedPath?: string): RouteGuard;
95
+ /**
96
+ * Create a confirmation guard that can be used for unsaved changes
97
+ */
98
+ export declare function createConfirmGuard(shouldConfirm: () => boolean, message?: string): RouteGuard;
99
+ /**
100
+ * Create a guest-only guard (redirects authenticated users)
101
+ */
102
+ export declare function createGuestGuard(isAuthenticated: () => boolean, homePath?: string): RouteGuard;
103
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,aAAa,EACb,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,UAAU,CAE5E;AAMD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAiC;IAE/C;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAOjC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI;IAMvC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIzC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC;;OAEG;IACH,KAAK,IAAI,MAAM,EAAE;IAIjB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC;CAGlC;AAmCD;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,GAClB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAWnD;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAS5D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,EACrC,QAAQ,EAAE,aAAa,GACtB,UAAU,EAAE,CAiCd;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,UAAU,EAAE,CAgC/F;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,MAAM,OAAO,EAC9B,SAAS,GAAE,MAAiB,GAC3B,UAAU,CASZ;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,EAClC,gBAAgB,GAAE,MAAwB,GACzC,UAAU,CAQZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,OAAO,EAC5B,OAAO,GAAE,MAAoE,GAC5E,UAAU,CAYZ;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,eAAe,EAAE,MAAM,OAAO,EAC9B,QAAQ,GAAE,MAAY,GACrB,UAAU,CAOZ"}