-
-
Notifications
You must be signed in to change notification settings - Fork 147
/
nav-route.ts
97 lines (86 loc) · 3.56 KB
/
nav-route.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { ICustomElementType, INode, IObserverLocator, IPropertyObserver, LifecycleFlags } from '@aurelia/runtime';
import { INavRoute, IViewportComponent, Nav, NavInstruction } from './nav';
import { Router } from './router';
import { ViewportInstruction } from './viewport-instruction';
export class NavRoute {
public nav: Nav;
public instructions: ViewportInstruction[];
public title: string;
public link?: string;
public linkActive?: string;
public children?: NavRoute[];
public meta?: Record<string, unknown>;
public active: string = '';
private readonly observerLocator: IObserverLocator;
private readonly observer: IPropertyObserver<Router, 'activeComponents'>;
constructor(nav: Nav, route?: INavRoute) {
this.nav = nav;
Object.assign(this, {
title: route.title,
children: null,
meta: route.meta,
active: '',
});
this.instructions = this.parseRoute(route.route);
this.link = this._link(this.instructions);
this.linkActive = route.consideredActive ? this._link(this.parseRoute(route.consideredActive)) : this.link;
this.observerLocator = this.nav.router.container.get(IObserverLocator);
this.observer = this.observerLocator.getObserver(LifecycleFlags.none, this.nav.router, 'activeComponents') as IPropertyObserver<Router, 'activeComponents'>;
this.observer.subscribe(this);
}
public get hasChildren(): string {
return (this.children && this.children.length ? 'nav-has-children' : '');
}
public handleChange(): void {
if (this.link && this.link.length) {
this.active = this._active();
} else {
this.active = (this.active === 'nav-active' ? 'nav-active' : (this.activeChild() ? 'nav-active-child' : ''));
}
}
public _active(): string {
const components = this.nav.router.instructionResolver.viewportInstructionsFromString(this.linkActive);
const activeComponents = this.nav.router.activeComponents.map((state) => this.nav.router.instructionResolver.parseViewportInstruction(state));
for (const component of components) {
if (!activeComponents.find((active) => active.sameComponent(component))) {
return '';
}
}
return 'nav-active';
}
public toggleActive(): void {
this.active = (this.active.startsWith('nav-active') ? '' : 'nav-active');
}
public _link(instructions: ViewportInstruction[]): string {
return this.nav.router.instructionResolver.viewportInstructionsToString(instructions);
}
private parseRoute(routes: NavInstruction | NavInstruction[]): ViewportInstruction[] {
if (!Array.isArray(routes)) {
return this.parseRoute([routes]);
}
const instructions: ViewportInstruction[] = [];
for (const route of routes) {
if (typeof route === 'string') {
instructions.push(this.nav.router.instructionResolver.parseViewportInstruction(route));
} else if (route as ViewportInstruction instanceof ViewportInstruction) {
instructions.push(route as ViewportInstruction);
} else if (route['component']) {
const viewportComponent = route as IViewportComponent;
instructions.push(new ViewportInstruction(viewportComponent.component, viewportComponent.viewport, viewportComponent.parameters));
} else {
instructions.push(new ViewportInstruction(route as Partial<ICustomElementType>));
}
}
return instructions;
}
private activeChild(): boolean {
if (this.children) {
for (const child of this.children) {
if (child.active.startsWith('nav-active') || child.activeChild()) {
return true;
}
}
}
return false;
}
}