@triptease/tt-navbar 0.0.15 → 0.0.18
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/src/TtNavbar.d.ts +4 -1
- package/dist/src/TtNavbar.js +53 -5
- package/dist/src/TtNavbar.js.map +1 -1
- package/dist/test/tt-navbar.test.js +22 -3
- package/dist/test/tt-navbar.test.js.map +1 -1
- package/dist/web/TtNavbar.js +54 -6
- package/dist/web/TtNavbar.js.map +2 -2
- package/dist/web/index.js +54 -6
- package/dist/web/index.js.map +2 -2
- package/dist/web/styles.js +1 -1
- package/dist/web/triptease-logo.js +1 -1
- package/dist/web/tt-navbar.js +54 -6
- package/dist/web/tt-navbar.js.map +2 -2
- package/package.json +1 -1
- package/src/TtNavbar.ts +59 -4
- package/test/tt-navbar.test.ts +29 -3
package/package.json
CHANGED
package/src/TtNavbar.ts
CHANGED
|
@@ -29,11 +29,66 @@ export class TtNavbar extends LitElement {
|
|
|
29
29
|
@property({ type: String, attribute: 'client-key' })
|
|
30
30
|
clientKey?: string;
|
|
31
31
|
|
|
32
|
+
@queryAll('details')
|
|
33
|
+
protected allDetailsElements!: Array<HTMLDetailsElement>;
|
|
34
|
+
|
|
35
|
+
@queryAll('a')
|
|
36
|
+
protected allNavLinks!: Array<HTMLAnchorElement>;
|
|
37
|
+
|
|
32
38
|
@state()
|
|
33
39
|
private sidebarOpen = true;
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
protected firstUpdated() {
|
|
42
|
+
this.setActiveState();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Set the active state for the current page.
|
|
47
|
+
*
|
|
48
|
+
* This function iterates over all nav links and compares the current URL path with the href of each link.
|
|
49
|
+
* If the current URL path starts with the href of a link, the link is marked as active. If multiple links
|
|
50
|
+
* share the same prefix, the longest prefix is used as it is more specific.
|
|
51
|
+
*
|
|
52
|
+
* Example:
|
|
53
|
+
* - Current URL: /channels/123
|
|
54
|
+
* - Nav links:
|
|
55
|
+
* - /channels
|
|
56
|
+
* - /channels/123
|
|
57
|
+
* - /channels/456
|
|
58
|
+
*
|
|
59
|
+
* Loop 1: currentPath = /channels/123, linkPath = /channels, bestMatch = /channels
|
|
60
|
+
* Loop 2: currentPath = /channels/123, linkPath = /channels/123, bestMatch = /channels/123
|
|
61
|
+
* Loop 3: currentPath = /channels/123, linkPath = /channels/456, bestMatch = /channels/123
|
|
62
|
+
* Result: /channels/123 is marked as active
|
|
63
|
+
*
|
|
64
|
+
*/
|
|
65
|
+
private setActiveState = () => {
|
|
66
|
+
const currentPath = window.location.pathname;
|
|
67
|
+
|
|
68
|
+
let bestMatch: HTMLAnchorElement | undefined;
|
|
69
|
+
let bestMatchLength = 0;
|
|
70
|
+
|
|
71
|
+
for (const link of this.allNavLinks) {
|
|
72
|
+
link.classList.remove('current-page');
|
|
73
|
+
if (link.hasAttribute('aria-current')) {
|
|
74
|
+
link.attributes.removeNamedItem('aria-current');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const linkPath = new URL(link.href).pathname;
|
|
78
|
+
|
|
79
|
+
if (currentPath.startsWith(linkPath)) {
|
|
80
|
+
if (linkPath.length > bestMatchLength) {
|
|
81
|
+
bestMatch = link;
|
|
82
|
+
bestMatchLength = linkPath.length;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (bestMatch) {
|
|
88
|
+
bestMatch.classList.add('current-page');
|
|
89
|
+
bestMatch.setAttribute('aria-current', 'page');
|
|
90
|
+
}
|
|
91
|
+
};
|
|
37
92
|
|
|
38
93
|
private closeAllDetails = (element?: HTMLDetailsElement) => {
|
|
39
94
|
this.allDetailsElements.forEach(detail => {
|
|
@@ -152,13 +207,13 @@ export class TtNavbar extends LitElement {
|
|
|
152
207
|
>
|
|
153
208
|
<a
|
|
154
209
|
class="sub-nav-item"
|
|
155
|
-
href=${this.buildUrl('/settings/
|
|
210
|
+
href=${this.buildUrl('/settings/$CLIENT_KEY/guides')}
|
|
156
211
|
@click=${this.onAnchorClick}
|
|
157
212
|
>Group settings</a
|
|
158
213
|
>
|
|
159
214
|
<a
|
|
160
215
|
class="sub-nav-item"
|
|
161
|
-
href=${this.buildUrl('/settings/$CLIENT_KEY/hotels
|
|
216
|
+
href=${this.buildUrl('/settings/$CLIENT_KEY/hotels')}
|
|
162
217
|
@click=${this.onAnchorClick}
|
|
163
218
|
>Property settings</a
|
|
164
219
|
>
|
package/test/tt-navbar.test.ts
CHANGED
|
@@ -63,8 +63,8 @@ describe('TtNavbar', () => {
|
|
|
63
63
|
expect(getLinkByHref(links, `/${CLIENT_KEY}/guest-behavioural-data`)).to
|
|
64
64
|
.exist;
|
|
65
65
|
expect(getLinkByHref(links, `/${CLIENT_KEY}/crm-config`)).to.exist;
|
|
66
|
-
expect(getLinkByHref(links, `/settings/
|
|
67
|
-
expect(getLinkByHref(links, `/settings/${CLIENT_KEY}/hotels
|
|
66
|
+
expect(getLinkByHref(links, `/settings/${CLIENT_KEY}/guides`)).to.exist;
|
|
67
|
+
expect(getLinkByHref(links, `/settings/${CLIENT_KEY}/hotels`)).to.exist;
|
|
68
68
|
expect(getLinkByHref(links, `/account`)).to.exist;
|
|
69
69
|
expect(getLinkByHref(links, `/account/team/${CLIENT_KEY}`)).to.exist;
|
|
70
70
|
expect(getLinkByHref(links, `/account/billing-management/${CLIENT_KEY}`))
|
|
@@ -229,7 +229,33 @@ describe('TtNavbar', () => {
|
|
|
229
229
|
|
|
230
230
|
element!.click();
|
|
231
231
|
|
|
232
|
-
await waitUntil(() => logo?.checkVisibility(),
|
|
232
|
+
await waitUntil(() => logo?.checkVisibility(), 'navbar should be open', {
|
|
233
|
+
timeout: 500,
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
const URLs = [
|
|
239
|
+
['/', 'Dashboard'],
|
|
240
|
+
['/channels', 'Channels'],
|
|
241
|
+
[`/parity/${CLIENT_KEY}`, 'Parity'],
|
|
242
|
+
[`/parity/${CLIENT_KEY}`, 'Parity'],
|
|
243
|
+
[`/parity/${CLIENT_KEY}/foo`, 'Parity'],
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
URLs.forEach(([route, text]) => {
|
|
247
|
+
it(`should show the current page as active when link is ${route}`, async () => {
|
|
248
|
+
// eslint-disable-next-line no-restricted-globals
|
|
249
|
+
history.pushState({}, '', route); // 👈 mock URL
|
|
250
|
+
|
|
251
|
+
const navbar = await fixture<TtNavbar>(
|
|
252
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
|
|
256
|
+
|
|
257
|
+
expect(anchor).to.exist;
|
|
258
|
+
expect(anchor!.textContent).to.include(text);
|
|
233
259
|
});
|
|
234
260
|
});
|
|
235
261
|
});
|