@triptease/tt-navbar 0.0.20 → 0.0.22

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @triptease/tt-navbar v0.0.20
2
+ * @triptease/tt-navbar v0.0.22
3
3
  */
4
4
 
5
5
  // src/urlMappings.ts
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent tt-navbar following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "tt-navbar",
6
- "version": "0.0.20",
6
+ "version": "0.0.22",
7
7
  "type": "module",
8
8
  "main": "dist/src/index.js",
9
9
  "module": "dist/src/index.js",
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@triptease/icons": "^1.1.1",
31
+ "@triptease/tt-combobox": "^5.2.1",
31
32
  "lit": "^3.1.4"
32
33
  },
33
34
  "devDependencies": {
package/src/Routes.ts ADDED
@@ -0,0 +1,5 @@
1
+ const Routes = {
2
+ CampaignManager: 'CampaignManager',
3
+ };
4
+
5
+ export { Routes };
package/src/TtNavbar.ts CHANGED
@@ -5,18 +5,29 @@ import {
5
5
  campaigns,
6
6
  channels,
7
7
  chevronDown,
8
+ external,
8
9
  gear,
9
10
  graph,
10
11
  home,
11
12
  logout,
12
- user,
13
- wallet,
14
- external,
15
13
  sidebarCollapsed,
14
+ user,
15
+ wallet
16
16
  } from '@triptease/icons';
17
+ import '@triptease/tt-combobox';
17
18
  import { styles } from './styles.js';
18
19
  import { tripteaseLogo } from './triptease-logo.js';
19
20
  import { urlMappings } from './urlMappings.js';
21
+ import { Routes } from './Routes.js';
22
+
23
+ const jsonArrayConverter = (value: string | null) => {
24
+ if (!value) return [];
25
+ try {
26
+ return JSON.parse(value);
27
+ } catch {
28
+ return [];
29
+ }
30
+ };
20
31
 
21
32
  export class TtNavbar extends LitElement {
22
33
  static styles = styles;
@@ -33,6 +44,15 @@ export class TtNavbar extends LitElement {
33
44
  @property({ type: String, attribute: 'client-key' })
34
45
  clientKey?: string;
35
46
 
47
+ @property({ type: String, attribute: 'active-route' })
48
+ activeRoute?: keyof typeof Routes;
49
+
50
+ @property({ type: Array, converter: jsonArrayConverter })
51
+ clients: { clientKey: string; displayName: string }[] = [];
52
+
53
+ @property({ type: Object })
54
+ onClientChange: ((clientKeySelected: string) => void ) | undefined;
55
+
36
56
  @queryAll('details')
37
57
  protected allDetailsElements!: Array<HTMLDetailsElement>;
38
58
 
@@ -73,12 +93,9 @@ export class TtNavbar extends LitElement {
73
93
  let bestMatchLength = 0;
74
94
 
75
95
  // Check special cases first, as everything will always match on / and return Dashboard
76
-
77
- if (this.campaignManagerUrl.includes(window.location.host)) {
96
+ if (this.activeRoute === Routes.CampaignManager) {
78
97
  const links = Object.values(this.allNavLinks);
79
- bestMatch = links.find(link =>
80
- link.href.includes(this.campaignManagerUrl),
81
- );
98
+ bestMatch = links.find(link => link.id === Routes.CampaignManager);
82
99
  }
83
100
 
84
101
  if (!bestMatch && this.clientKey) {
@@ -184,7 +201,7 @@ export class TtNavbar extends LitElement {
184
201
  @click=${this.onAnchorClick}
185
202
  >${unsafeSVG(home)}<span>Dashboard</span></a
186
203
  >
187
- <a class="nav-item" href=${this.campaignManagerUrl}
204
+ <a id="${Routes.CampaignManager}" class="nav-item" href=${this.campaignManagerUrl}
188
205
  >${unsafeSVG(campaigns)}<span>Campaigns</span></a
189
206
  >
190
207
  <a
@@ -323,7 +340,25 @@ export class TtNavbar extends LitElement {
323
340
  <hr />
324
341
  </div>
325
342
  <div class='nav-items'>
326
- <slot id="client-selector" name="clientSelector"></slot>
343
+ <div id="client-selector">
344
+ ${this.clients.length > 1 ? html`
345
+ <tt-combobox
346
+ .openUpward=${true}
347
+ .value=${this.clientKey}
348
+ .onChange=${this.onClientChange}
349
+ >
350
+ ${this.clients.map((client) => html`
351
+ <option slot="option" value=${client.clientKey}>
352
+ ${client.displayName}
353
+ </option>
354
+ `)}
355
+ </tt-combobox>
356
+ ` : html`
357
+ <div class="single-client-name">
358
+ ${this.clients.find((m) => m.clientKey === this.clientKey)?.displayName}
359
+ </div>
360
+ `}
361
+ </div>
327
362
  <a
328
363
  id="logout-link"
329
364
  class="nav-item"
@@ -331,7 +366,6 @@ export class TtNavbar extends LitElement {
331
366
  @click=${this.onAnchorClick}
332
367
  >${unsafeSVG(logout)}<span>Logout</span></a>
333
368
  </div>
334
- <div>
335
369
  </nav>
336
370
  `;
337
371
  }
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { TtNavbar } from './TtNavbar.js';
2
+ export { Routes } from './Routes.js';
package/src/styles.ts CHANGED
@@ -107,8 +107,8 @@ export const styles = css`
107
107
 
108
108
  .tertiary-nav.sidebar-closed {
109
109
  .external-link,
110
- slot,
111
- hr {
110
+ hr,
111
+ #client-selector {
112
112
  display: none;
113
113
  visibility: hidden;
114
114
  }
@@ -336,4 +336,29 @@ export const styles = css`
336
336
  visibility: visible;
337
337
  opacity: 1;
338
338
  }
339
+
340
+ #client-selector {
341
+ display: flex;
342
+ align-items: center;
343
+ }
344
+
345
+ #client-selector tt-combobox {
346
+ --tt-combobox-color: var(--color-text-inverted-400);
347
+ --tt-combobox-dropdown-color: var(--color-text-inverted-400);
348
+ --tt-combobox-list-background-color: var(--color-surface-inverted-100);
349
+ --tt-combobox-option-background-color-hover: var(--color-surface-inverted-200);
350
+ --tt-combobox-placeholder-color: var(--color-text-inverted-300);
351
+ --tt-combobox-background-color: var(--color-surface-inverted-100);
352
+ --tt-combobox-hover-background-color: var(--color-surface-inverted-200);
353
+ --tt-combobox-list-max-width: 80ch;
354
+ --tt-combobox-min-width: 244px;
355
+ --tt-combobox-max-width: 244px;
356
+ }
357
+
358
+ .single-client-name {
359
+ height: 39px;
360
+ padding: var(--space-scale-1); /* match tt-combobox height */
361
+ font-size: var(--font-size-100);
362
+ color: var(--color-text-inverted-400);
363
+ }
339
364
  `;
@@ -1,22 +1,64 @@
1
- import { html } from 'lit';
1
+ import { html, TemplateResult } from 'lit';
2
2
  import '../src/tt-navbar.js';
3
3
 
4
- export default {
4
+ const meta = {
5
5
  title: 'TtNavbar',
6
6
  component: 'tt-navbar',
7
+ argTypes: {
8
+ clientKey: { control: 'text' },
9
+ clients: { control: 'object' },
10
+ campaignManagerUrl: { control: 'text' }
11
+ }
7
12
  };
8
13
 
9
- const Template = () => html`
14
+ export default meta;
15
+
16
+ interface Story<T> {
17
+ (args: T): TemplateResult;
18
+
19
+ args?: Partial<T>;
20
+ argTypes?: Record<string, unknown>;
21
+ }
22
+
23
+ interface Client {
24
+ clientKey: string;
25
+ displayName: string;
26
+ }
27
+
28
+ interface ArgTypes {
29
+ clientKey?: string;
30
+ clients?: Client[];
31
+ campaignManagerUrl?: string;
32
+ }
33
+
34
+ const Template: Story<ArgTypes> = ({
35
+ clientKey = 'zxd47KQGAP',
36
+ clients = [],
37
+ campaignManagerUrl = 'https://app.campaign-manager.triptease.io'
38
+ }: ArgTypes) => html`
10
39
  <div>
11
40
  <tt-navbar
12
- client-key="zxd47KQGAP"
13
- campaign-manager-url="https://app.campaign-manager.triptease.io"
41
+ client-key=${clientKey}
42
+ campaign-manager-url=${campaignManagerUrl}
43
+ .clients=${clients}
14
44
  >
15
- <div slot="clientSelector">
16
- <p>My Cool Client Selector</p>
17
- </div>
18
45
  </tt-navbar>
19
46
  </div>
20
47
  `;
21
48
 
22
- export const Regular = Template.bind({});
49
+ export const MultipleClients = Template.bind({});
50
+ MultipleClients.args = {
51
+ clientKey: 'zxd47KQGAP',
52
+ clients: [
53
+ { clientKey: 'zxd47KQGAP', displayName: 'Demo Client' },
54
+ { clientKey: 'a1b2c3d4e5', displayName: 'Another Client' }
55
+ ]
56
+ };
57
+
58
+ export const SingleClient = Template.bind({});
59
+ SingleClient.args = {
60
+ clientKey: 'zxd47KQGAP',
61
+ clients: [
62
+ { clientKey: 'zxd47KQGAP', displayName: 'Demo Client' }
63
+ ]
64
+ };
@@ -7,6 +7,7 @@ import {
7
7
  waitUntil,
8
8
  } from '@open-wc/testing';
9
9
  import { TtNavbar } from '../src/index.js';
10
+ import { Routes } from '../src/Routes.js';
10
11
 
11
12
  // eslint-disable-next-line no-undef
12
13
  const getLinkByHref = (links: NodeListOf<HTMLAnchorElement>, href: string) => {
@@ -111,14 +112,38 @@ describe('TtNavbar', () => {
111
112
  );
112
113
  });
113
114
 
114
- it('should render the given client selector', async () => {
115
+ it('should render a combobox when multiple clients are provided', async () => {
115
116
  const navbar = await fixture<TtNavbar>(
116
- `<tt-navbar client-key=${CLIENT_KEY}><div slot="clientSelector"><div id="myCoolClientSelector"></div></div></tt-navbar>`,
117
+ `<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
118
+ );
119
+ navbar.clients = [
120
+ { clientKey: CLIENT_KEY, displayName: 'Client One' },
121
+ { clientKey: 'abc123', displayName: 'Client Two' },
122
+ ];
123
+ await navbar.updateComplete;
124
+
125
+ const combobox = navbar.shadowRoot?.querySelector('tt-combobox');
126
+ const singleClientName = navbar.shadowRoot?.querySelector('.single-client-name');
127
+
128
+ expect(combobox).to.exist;
129
+ expect(singleClientName).to.not.exist;
130
+ });
131
+
132
+ it('should render the client name when only one client is provided', async () => {
133
+ const navbar = await fixture<TtNavbar>(
134
+ `<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
117
135
  );
136
+ navbar.clients = [
137
+ { clientKey: CLIENT_KEY, displayName: 'Single Client' },
138
+ ];
139
+ await navbar.updateComplete;
118
140
 
119
- const clientSelector = navbar.querySelector('#myCoolClientSelector');
141
+ const singleClientName = navbar.shadowRoot?.querySelector('.single-client-name');
142
+ const combobox = navbar.shadowRoot?.querySelector('tt-combobox');
120
143
 
121
- expect(clientSelector).to.exist;
144
+ expect(singleClientName).to.exist;
145
+ expect(singleClientName?.textContent?.trim()).to.equal('Single Client');
146
+ expect(combobox).to.not.exist;
122
147
  });
123
148
 
124
149
  it('should render the logout link', async () => {
@@ -267,7 +292,7 @@ describe('TtNavbar', () => {
267
292
  const campaignManagerUrl = 'http://localhost:8000';
268
293
 
269
294
  const navbar = await fixture<TtNavbar>(
270
- `<tt-navbar client-key=${CLIENT_KEY} platform-url=${platformUrl} campaign-manager-url=${campaignManagerUrl}></tt-navbar>`,
295
+ `<tt-navbar client-key=${CLIENT_KEY} platform-url=${platformUrl} campaign-manager-url=${campaignManagerUrl} active-route="${Routes.CampaignManager}"></tt-navbar>`,
271
296
  );
272
297
  const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
273
298
  expect(anchor).to.exist;