@record-evolution/widget-navbar 1.0.11 → 1.0.13

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,18 +1,18 @@
1
- import { LitElement as u, css as m, nothing as g, html as a } from "lit";
2
- import { property as l, state as d } from "lit/decorators.js";
3
- import { repeat as f } from "lit/directives/repeat.js";
1
+ import { LitElement as m, css as d, nothing as f, html as l } from "lit";
2
+ import { property as a, state as u } from "lit/decorators.js";
3
+ import { repeat as g } from "lit/directives/repeat.js";
4
4
  import "@material/web/icon/icon";
5
5
  import "@material/web/tabs/tabs";
6
6
  import "@material/web/tabs/primary-tab";
7
7
  import "@material/web/tabs/secondary-tab";
8
- var b = Object.defineProperty, n = (c, t, e, i) => {
9
- for (var s = void 0, o = c.length - 1, p; o >= 0; o--)
10
- (p = c[o]) && (s = p(t, e, s) || s);
11
- return s && b(t, e, s), s;
8
+ var b = Object.defineProperty, n = (p, t, e, i) => {
9
+ for (var r = void 0, o = p.length - 1, c; o >= 0; o--)
10
+ (c = p[o]) && (r = c(t, e, r) || r);
11
+ return r && b(t, e, r), r;
12
12
  };
13
- const h = class h extends u {
13
+ const h = class h extends m {
14
14
  constructor() {
15
- super(...arguments), this.version = "1.0.11";
15
+ super(...arguments), this.version = "1.0.13";
16
16
  }
17
17
  update(t) {
18
18
  t.has("theme") && this.registerTheme(this.theme), super.update(t);
@@ -38,8 +38,18 @@ const h = class h extends u {
38
38
  trimRoute(t) {
39
39
  return t ? "/" + t.split("/").filter(Boolean).join("/") : "";
40
40
  }
41
- addSlashes(t) {
42
- return !t.route?.endsWith("/") && t.trailingSlash && (t.route += "/"), !t.route?.startsWith("/") && t.leadingSlash && (t.route = "/" + t.route), t.route;
41
+ resolveRoute(t) {
42
+ let e = String(t?.route ?? "");
43
+ if (t?.variables)
44
+ for (const i of t.variables)
45
+ i.label && (e = e.split(`{{${i.label}}}`).join(encodeURIComponent(String(i.value ?? ""))));
46
+ if (e.includes("*")) {
47
+ const i = (this.route || "").split("/").filter(Boolean), r = e.split("/").filter(Boolean);
48
+ for (let o = 0; o < r.length; o++)
49
+ r[o] === "*" && (r[o] = i[o] ?? "");
50
+ e = (e.startsWith("/") ? "/" : "") + r.filter(Boolean).join("/");
51
+ }
52
+ return e;
43
53
  }
44
54
  matchesRoute(t) {
45
55
  if (t === void 0) return !1;
@@ -47,11 +57,11 @@ const h = class h extends u {
47
57
  return t.startsWith("/") ? e.startsWith(i) : e.endsWith(i) || e === i;
48
58
  }
49
59
  render() {
50
- const t = this.inputData?.style?.fontSize ?? 16, e = (this.inputData?.style?.fontSize ?? 16) * 1.5, i = this.inputData?.style?.color || this.themeTitleColor || "black", s = this.inputData?.style?.backgroundColor || this.themeBgColor || "white";
51
- return a`
60
+ const t = this.inputData?.style?.fontSize ?? 16, e = (this.inputData?.style?.fontSize ?? 16) * 1.5, i = this.inputData?.style?.color || this.themeTitleColor || "black", r = this.inputData?.style?.backgroundColor || this.themeBgColor || "white";
61
+ return l`
52
62
  <div
53
63
  class="wrapper"
54
- style="background-color: ${s}; color: ${i};
64
+ style="background-color: ${r}; color: ${i};
55
65
  font-weight: ${this.inputData?.style?.fontWeight};
56
66
  font-size: ${t}px;"
57
67
  >
@@ -59,30 +69,35 @@ const h = class h extends u {
59
69
  class="paging"
60
70
  style=${this.inputData?.route ? "cursor: pointer" : ""}
61
71
  ?active=${this.inputData?.title}
62
- @click=${() => this.handleNavItemClick(this.addSlashes(this.inputData))}
72
+ @click=${() => this.handleNavItemClick(
73
+ this.resolveRoute({
74
+ route: this.inputData?.route,
75
+ variables: this.inputData?.variables
76
+ })
77
+ )}
63
78
  >
64
79
  ${this.inputData?.title}
65
80
  </h2>
66
81
  <md-tab class="xnav-list">
67
- ${f(
82
+ ${g(
68
83
  this.inputData?.navItems || [],
69
84
  (o) => o.label,
70
- (o) => a`
85
+ (o) => l`
71
86
  <md-secondary-tab
72
- ?active=${this.matchesRoute(this.addSlashes(o))}
87
+ ?active=${this.matchesRoute(this.resolveRoute(o))}
73
88
  style="font-size: ${t}px;
74
- --md-secondary-tab-container-color: ${s};
89
+ --md-secondary-tab-container-color: ${r};
75
90
  color: ${i};"
76
- @click=${() => this.handleNavItemClick(this.addSlashes(o))}
91
+ @click=${() => this.handleNavItemClick(this.resolveRoute(o))}
77
92
  >
78
- ${o.iconName ? a`
93
+ ${o.iconName ? l`
79
94
  <md-icon
80
95
  slot="icon"
81
96
  style="font-size: ${e}px;width: ${e}px;color: ${i}"
82
97
  >
83
98
  ${o.iconName}
84
99
  </md-icon>
85
- ` : g}
100
+ ` : f}
86
101
  ${o.label}
87
102
  </md-secondary-tab>
88
103
  `
@@ -92,7 +107,7 @@ const h = class h extends u {
92
107
  `;
93
108
  }
94
109
  };
95
- h.styles = m`
110
+ h.styles = d`
96
111
  :host {
97
112
  display: block;
98
113
  font-family: sans-serif;
@@ -109,6 +124,7 @@ h.styles = m`
109
124
  align-items: end;
110
125
  height: 100%;
111
126
  width: 100%;
127
+ padding: 0 16px;
112
128
  box-sizing: border-box;
113
129
  }
114
130
 
@@ -129,24 +145,24 @@ h.styles = m`
129
145
  height: 48px;
130
146
  }
131
147
  `;
132
- let r = h;
148
+ let s = h;
133
149
  n([
134
- l({ type: Object })
135
- ], r.prototype, "inputData");
150
+ a({ type: Object })
151
+ ], s.prototype, "inputData");
136
152
  n([
137
- l({ type: Object })
138
- ], r.prototype, "theme");
153
+ a({ type: Object })
154
+ ], s.prototype, "theme");
139
155
  n([
140
- l({ type: String })
141
- ], r.prototype, "route");
156
+ a({ type: String })
157
+ ], s.prototype, "route");
142
158
  n([
143
- d()
144
- ], r.prototype, "themeBgColor");
159
+ u()
160
+ ], s.prototype, "themeBgColor");
145
161
  n([
146
- d()
147
- ], r.prototype, "themeTitleColor");
148
- window.customElements.define("widget-navbar-1.0.11", r);
162
+ u()
163
+ ], s.prototype, "themeTitleColor");
164
+ window.customElements.define("widget-navbar-1.0.13", s);
149
165
  export {
150
- r as WidgetNavbar
166
+ s as WidgetNavbar
151
167
  };
152
168
  //# sourceMappingURL=widget-navbar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"widget-navbar.js","sources":["../src/widget-navbar.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues, nothing } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { InputData } from './definition-schema'\n\nimport '@material/web/icon/icon'\nimport '@material/web/tabs/tabs'\nimport '@material/web/tabs/primary-tab'\nimport '@material/web/tabs/secondary-tab'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\nexport class WidgetNavbar extends LitElement {\n @property({ type: Object }) inputData?: InputData\n @property({ type: Object }) theme?: Theme\n @property({ type: String }) route?: string\n\n @state() private themeBgColor?: string\n @state() private themeTitleColor?: string\n\n version: string = 'versionplaceholder'\n\n update(changedProperties: Map<string, any>) {\n if (changedProperties.has('theme')) {\n this.registerTheme(this.theme)\n }\n\n super.update(changedProperties)\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n this.registerTheme(this.theme)\n }\n\n registerTheme(theme?: Theme) {\n const cssTextColor = getComputedStyle(this).getPropertyValue('--re-text-color').trim()\n const cssBgColor = getComputedStyle(this).getPropertyValue('--re-tile-background-color').trim()\n this.themeBgColor = cssBgColor || this.theme?.theme_object?.backgroundColor\n this.themeTitleColor = cssTextColor || this.theme?.theme_object?.title?.textStyle?.color\n }\n\n handleNavItemClick(route?: string) {\n // console.log('Navigating to:', item.route)\n const event = new CustomEvent('nav-submit', {\n detail: { path: route },\n bubbles: true,\n composed: true\n })\n this.dispatchEvent(event)\n }\n\n normalizeRoute(route?: string) {\n if (!route) return '/'\n return route\n }\n\n static styles = css`\n :host {\n display: block;\n font-family: sans-serif;\n box-sizing: border-box;\n margin: auto;\n }\n\n .paging:not([active]) {\n display: none !important;\n }\n\n .wrapper {\n display: flex;\n align-items: end;\n height: 100%;\n width: 100%;\n box-sizing: border-box;\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n }\n\n .selected {\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.1);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\n font-size: 1.2em;\n line-height: 2.5;\n height: 48px;\n }\n `\n\n trimRoute(route?: string) {\n if (!route) return ''\n return '/' + route.split('/').filter(Boolean).join('/')\n }\n\n addSlashes(item?: any): string | undefined {\n if (!item.route?.endsWith('/') && item.trailingSlash) {\n item.route += '/'\n }\n if (!item.route?.startsWith('/') && item.leadingSlash) {\n item.route = '/' + item.route\n }\n return item.route\n }\n\n matchesRoute(itemRoute?: string) {\n if (itemRoute === undefined) return false\n const route = this.trimRoute(decodeURIComponent(this.route || '/'))\n const subRoute = this.trimRoute(itemRoute)\n if (itemRoute.startsWith('/')) {\n return route.startsWith(subRoute)\n } else {\n return route.endsWith(subRoute) || route === subRoute\n }\n }\n\n render() {\n const fontSize = this.inputData?.style?.fontSize ?? 16\n const iconFontSize = (this.inputData?.style?.fontSize ?? 16) * 1.5\n const fontColor = this.inputData?.style?.color || this.themeTitleColor || 'black'\n const bgColor = this.inputData?.style?.backgroundColor || this.themeBgColor || 'white'\n return html`\n <div\n class=\"wrapper\"\n style=\"background-color: ${bgColor}; color: ${fontColor};\n font-weight: ${this.inputData?.style?.fontWeight};\n font-size: ${fontSize}px;\"\n >\n <h2\n class=\"paging\"\n style=${this.inputData?.route ? 'cursor: pointer' : ''}\n ?active=${this.inputData?.title}\n @click=${() => this.handleNavItemClick(this.addSlashes(this.inputData))}\n >\n ${this.inputData?.title}\n </h2>\n <md-tab class=\"xnav-list\">\n ${repeat(\n this.inputData?.navItems || [],\n (item) => item.label,\n (item) => html`\n <md-secondary-tab\n ?active=${this.matchesRoute(this.addSlashes(item))}\n style=\"font-size: ${fontSize}px;\n --md-secondary-tab-container-color: ${bgColor};\n color: ${fontColor};\"\n @click=${() => this.handleNavItemClick(this.addSlashes(item))}\n >\n ${item.iconName\n ? html`\n <md-icon\n slot=\"icon\"\n style=\"font-size: ${iconFontSize}px;width: ${iconFontSize}px;color: ${fontColor}\"\n >\n ${item.iconName}\n </md-icon>\n `\n : nothing}\n ${item.label}\n </md-secondary-tab>\n `\n )}\n </md-tab>\n </div>\n `\n }\n}\nwindow.customElements.define('widget-navbar-versionplaceholder', WidgetNavbar)\n"],"names":["_WidgetNavbar","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","route","event","item","itemRoute","subRoute","fontSize","iconFontSize","fontColor","bgColor","html","repeat","nothing","css","WidgetNavbar","__decorateClass","property","state"],"mappings":"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"}
1
+ {"version":3,"file":"widget-navbar.js","sources":["../src/widget-navbar.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues, nothing } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { InputData } from './definition-schema'\n\nimport '@material/web/icon/icon'\nimport '@material/web/tabs/tabs'\nimport '@material/web/tabs/primary-tab'\nimport '@material/web/tabs/secondary-tab'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\nexport class WidgetNavbar extends LitElement {\n @property({ type: Object }) inputData?: InputData\n @property({ type: Object }) theme?: Theme\n @property({ type: String }) route?: string\n\n @state() private themeBgColor?: string\n @state() private themeTitleColor?: string\n\n version: string = 'versionplaceholder'\n\n update(changedProperties: Map<string, any>) {\n if (changedProperties.has('theme')) {\n this.registerTheme(this.theme)\n }\n\n super.update(changedProperties)\n }\n\n protected firstUpdated(_changedProperties: PropertyValues): void {\n this.registerTheme(this.theme)\n }\n\n registerTheme(theme?: Theme) {\n const cssTextColor = getComputedStyle(this).getPropertyValue('--re-text-color').trim()\n const cssBgColor = getComputedStyle(this).getPropertyValue('--re-tile-background-color').trim()\n this.themeBgColor = cssBgColor || this.theme?.theme_object?.backgroundColor\n this.themeTitleColor = cssTextColor || this.theme?.theme_object?.title?.textStyle?.color\n }\n\n handleNavItemClick(route?: string) {\n // console.log('Navigating to:', item.route)\n const event = new CustomEvent('nav-submit', {\n detail: { path: route },\n bubbles: true,\n composed: true\n })\n this.dispatchEvent(event)\n }\n\n normalizeRoute(route?: string) {\n if (!route) return '/'\n return route\n }\n\n static styles = css`\n :host {\n display: block;\n font-family: sans-serif;\n box-sizing: border-box;\n margin: auto;\n }\n\n .paging:not([active]) {\n display: none !important;\n }\n\n .wrapper {\n display: flex;\n align-items: end;\n height: 100%;\n width: 100%;\n padding: 0 16px;\n box-sizing: border-box;\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n }\n\n .selected {\n font-weight: bold;\n background-color: rgba(0, 0, 0, 0.1);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\n font-size: 1.2em;\n line-height: 2.5;\n height: 48px;\n }\n `\n\n trimRoute(route?: string) {\n if (!route) return ''\n return '/' + route.split('/').filter(Boolean).join('/')\n }\n\n resolveRoute(item?: any): string | undefined {\n let route = String(item?.route ?? '')\n if (item?.variables) {\n for (const variable of item.variables) {\n if (variable.label) {\n route = route\n .split(`{{${variable.label}}}`)\n .join(encodeURIComponent(String(variable.value ?? '')))\n }\n }\n }\n if (route.includes('*')) {\n const currentSegments = (this.route || '').split('/').filter(Boolean)\n const routeSegments = route.split('/').filter(Boolean)\n for (let i = 0; i < routeSegments.length; i++) {\n if (routeSegments[i] === '*') {\n routeSegments[i] = currentSegments[i] ?? ''\n }\n }\n route = (route.startsWith('/') ? '/' : '') + routeSegments.filter(Boolean).join('/')\n }\n return route\n }\n\n matchesRoute(itemRoute?: string) {\n if (itemRoute === undefined) return false\n const route = this.trimRoute(decodeURIComponent(this.route || '/'))\n const subRoute = this.trimRoute(itemRoute)\n if (itemRoute.startsWith('/')) {\n return route.startsWith(subRoute)\n } else {\n return route.endsWith(subRoute) || route === subRoute\n }\n }\n\n render() {\n const fontSize = this.inputData?.style?.fontSize ?? 16\n const iconFontSize = (this.inputData?.style?.fontSize ?? 16) * 1.5\n const fontColor = this.inputData?.style?.color || this.themeTitleColor || 'black'\n const bgColor = this.inputData?.style?.backgroundColor || this.themeBgColor || 'white'\n return html`\n <div\n class=\"wrapper\"\n style=\"background-color: ${bgColor}; color: ${fontColor};\n font-weight: ${this.inputData?.style?.fontWeight};\n font-size: ${fontSize}px;\"\n >\n <h2\n class=\"paging\"\n style=${this.inputData?.route ? 'cursor: pointer' : ''}\n ?active=${this.inputData?.title}\n @click=${() =>\n this.handleNavItemClick(\n this.resolveRoute({\n route: this.inputData?.route,\n variables: this.inputData?.variables\n })\n )}\n >\n ${this.inputData?.title}\n </h2>\n <md-tab class=\"xnav-list\">\n ${repeat(\n this.inputData?.navItems || [],\n (item) => item.label,\n (item) => html`\n <md-secondary-tab\n ?active=${this.matchesRoute(this.resolveRoute(item))}\n style=\"font-size: ${fontSize}px;\n --md-secondary-tab-container-color: ${bgColor};\n color: ${fontColor};\"\n @click=${() => this.handleNavItemClick(this.resolveRoute(item))}\n >\n ${item.iconName\n ? html`\n <md-icon\n slot=\"icon\"\n style=\"font-size: ${iconFontSize}px;width: ${iconFontSize}px;color: ${fontColor}\"\n >\n ${item.iconName}\n </md-icon>\n `\n : nothing}\n ${item.label}\n </md-secondary-tab>\n `\n )}\n </md-tab>\n </div>\n `\n }\n}\nwindow.customElements.define('widget-navbar-versionplaceholder', WidgetNavbar)\n"],"names":["_WidgetNavbar","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","route","event","item","variable","currentSegments","routeSegments","i","itemRoute","subRoute","fontSize","iconFontSize","fontColor","bgColor","html","repeat","nothing","css","WidgetNavbar","__decorateClass","property","state"],"mappings":"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"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent widget-navbar following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "widget-navbar",
6
- "version": "1.0.11",
6
+ "version": "1.0.13",
7
7
  "engines": {
8
8
  "node": ">=24.9.0",
9
9
  "npm": ">=10.0.2"
@@ -5,56 +5,91 @@
5
5
  * and run json-schema-to-typescript to regenerate this file.
6
6
  */
7
7
 
8
+ /**
9
+ * The main title/brand text displayed in the navigation bar, typically on the left side. Often used for logo text or application name.
10
+ */
8
11
  export type TitleSettings = string;
9
12
  /**
10
- * Navigation to perform on title click. Example: If you are at route /my/route/asset then 'settings/profile' routes to '/my/route/settings/profile'.
13
+ * The destination path when the title is clicked. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Title Navigation Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/* /settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.
11
14
  */
12
15
  export type TitleNavigation = string;
13
16
  /**
14
- * Whether to add a leading slash to the navigation route.
17
+ * The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.
18
+ */
19
+ export type Label = string;
20
+ /**
21
+ * The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.
15
22
  */
16
- export type AddLeadingSlash = boolean;
23
+ export type Value = string;
17
24
  /**
18
- * Whether to add a trailing slash to the navigation route.
25
+ * Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.
26
+ */
27
+ export type TitleNavigationVariables = {
28
+ label?: Label;
29
+ value?: Value;
30
+ [k: string]: unknown;
31
+ }[];
32
+ /**
33
+ * Font size in pixels for navigation item labels.
19
34
  */
20
- export type AddTraillingSlash = boolean;
21
35
  export type FontSize = number;
36
+ /**
37
+ * Font weight for navigation items (100=thin, 400=normal, 700=bold, 900=black).
38
+ */
22
39
  export type FontWeight = number;
23
- export type Label = string;
24
40
  /**
25
- * Name of the icon from https://fonts.google.com/icons
41
+ * The text displayed for this navigation item. Should be short and descriptive (e.g., 'Dashboard', 'Settings', 'Reports').
42
+ */
43
+ export type Label1 = string;
44
+ /**
45
+ * Material icon name to display alongside the label. Find icon names at https://fonts.google.com/icons (e.g., 'home', 'settings', 'dashboard', 'analytics').
26
46
  */
27
47
  export type IconName = string;
28
48
  /**
29
- * Navigation to perform on click. Example: If you are at route /my/route/asset then 'settings/profile' routes to '/my/route/settings/profile'.
49
+ * The destination path when this item is clicked. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/* /settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.
30
50
  */
31
51
  export type NavigationRoute = string;
32
52
  /**
33
- * Whether to add a leading slash to the navigation route.
53
+ * The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.
34
54
  */
35
- export type AddLeadingSlash1 = boolean;
55
+ export type Label2 = string;
36
56
  /**
37
- * Whether to add a trailing slash to the navigation route.
57
+ * The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.
58
+ */
59
+ export type Value1 = string;
60
+ /**
61
+ * Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.
62
+ */
63
+ export type NavigationVariables = {
64
+ label?: Label2;
65
+ value?: Value1;
66
+ [k: string]: unknown;
67
+ }[];
68
+ /**
69
+ * Array of clickable navigation links displayed in the navigation bar. Each item can have a label, icon, and destination route.
38
70
  */
39
- export type AddTraillingSlash1 = boolean;
40
71
  export type NavigationItems = {
41
- label?: Label;
72
+ label?: Label1;
42
73
  iconName?: IconName;
43
74
  route?: NavigationRoute;
44
- leadingSlash?: AddLeadingSlash1;
45
- trailingSlash?: AddTraillingSlash1;
75
+ variables?: NavigationVariables;
46
76
  [k: string]: unknown;
47
77
  }[];
48
78
 
79
+ /**
80
+ * A horizontal navigation bar widget for creating top-level dashboard navigation. Use this widget to provide consistent navigation across dashboard pages with a clickable title and multiple navigation items. Each item can have an icon and routes to different dashboard sections. Supports customizable styling for font size, weight, and colors. Ideal for multi-page dashboards requiring clear navigation structure and branding.
81
+ */
49
82
  export interface InputData {
50
83
  title?: TitleSettings;
51
84
  route?: TitleNavigation;
52
- leadingSlash?: AddLeadingSlash;
53
- trailingSlash?: AddTraillingSlash;
85
+ variables?: TitleNavigationVariables;
54
86
  style?: ItemStyle;
55
87
  navItems?: NavigationItems;
56
88
  [k: string]: unknown;
57
89
  }
90
+ /**
91
+ * Global styling options applied to all navigation items in the bar.
92
+ */
58
93
  export interface ItemStyle {
59
94
  fontSize?: FontSize;
60
95
  fontWeight?: FontWeight;
@@ -62,9 +97,15 @@ export interface ItemStyle {
62
97
  backgroundColor?: BackgroundColor;
63
98
  [k: string]: unknown;
64
99
  }
100
+ /**
101
+ * Text color for navigation item labels.
102
+ */
65
103
  export interface FontColor {
66
104
  [k: string]: unknown;
67
105
  }
106
+ /**
107
+ * Background color of the navigation bar.
108
+ */
68
109
  export interface BackgroundColor {
69
110
  [k: string]: unknown;
70
111
  }
@@ -1,57 +1,74 @@
1
1
  {
2
2
  "title": "Input Data",
3
+ "description": "A horizontal navigation bar widget for creating top-level dashboard navigation. Use this widget to provide consistent navigation across dashboard pages with a clickable title and multiple navigation items. Each item can have an icon and routes to different dashboard sections. Supports customizable styling for font size, weight, and colors. Ideal for multi-page dashboards requiring clear navigation structure and branding.",
3
4
  "type": "object",
4
5
  "properties": {
5
6
  "title": {
6
7
  "title": "Title Settings",
8
+ "description": "The main title/brand text displayed in the navigation bar, typically on the left side. Often used for logo text or application name.",
7
9
  "order": 1,
8
10
  "type": "string"
9
11
  },
10
12
  "route": {
11
13
  "title": "Title Navigation",
12
14
  "order": 3,
13
- "description": "Navigation to perform on title click. Example: If you are at route /my/route/asset then 'settings/profile' routes to '/my/route/settings/profile'.",
15
+ "description": "The destination path when the title is clicked. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Title Navigation Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/*/settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.",
14
16
  "type": "string"
15
17
  },
16
- "leadingSlash": {
17
- "title": "Add Leading Slash",
18
- "order": 4,
19
- "description": "Whether to add a leading slash to the navigation route.",
20
- "dataDrivenDisabled": true,
21
- "type": "boolean"
22
- },
23
- "trailingSlash": {
24
- "title": "Add Trailling Slash",
25
- "order": 5,
26
- "description": "Whether to add a trailing slash to the navigation route.",
18
+ "variables": {
19
+ "title": "Title Navigation Variables",
20
+ "description": "Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.",
21
+ "type": "array",
27
22
  "dataDrivenDisabled": true,
28
- "type": "boolean"
23
+ "order": 4,
24
+ "items": {
25
+ "type": "object",
26
+ "properties": {
27
+ "label": {
28
+ "title": "Label",
29
+ "description": "The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.",
30
+ "type": "string",
31
+ "order": 1
32
+ },
33
+ "value": {
34
+ "title": "Value",
35
+ "description": "The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.",
36
+ "type": "string",
37
+ "order": 2
38
+ }
39
+ }
40
+ }
29
41
  },
30
42
  "style": {
31
43
  "title": "Item Style",
44
+ "description": "Global styling options applied to all navigation items in the bar.",
32
45
  "order": 6,
33
46
  "type": "object",
34
47
  "properties": {
35
48
  "fontSize": {
36
49
  "title": "Font Size",
50
+ "description": "Font size in pixels for navigation item labels.",
37
51
  "order": 1,
38
52
  "dataDrivenDisabled": true,
39
53
  "type": "number"
40
54
  },
41
55
  "fontWeight": {
42
56
  "title": "Font Weight",
57
+ "description": "Font weight for navigation items (100=thin, 400=normal, 700=bold, 900=black).",
43
58
  "order": 3,
44
59
  "dataDrivenDisabled": true,
45
60
  "type": "number"
46
61
  },
47
62
  "color": {
48
63
  "title": "Font Color",
64
+ "description": "Text color for navigation item labels.",
49
65
  "order": 4,
50
66
  "type": "color",
51
67
  "dataDrivenDisabled": true
52
68
  },
53
69
  "backgroundColor": {
54
70
  "title": "Background Color",
71
+ "description": "Background color of the navigation bar.",
55
72
  "order": 4,
56
73
  "type": "color",
57
74
  "dataDrivenDisabled": true
@@ -60,6 +77,7 @@
60
77
  },
61
78
  "navItems": {
62
79
  "title": "Navigation Items",
80
+ "description": "Array of clickable navigation links displayed in the navigation bar. Each item can have a label, icon, and destination route.",
63
81
  "order": 7,
64
82
  "type": "array",
65
83
  "items": {
@@ -67,35 +85,46 @@
67
85
  "properties": {
68
86
  "label": {
69
87
  "title": "Label",
88
+ "description": "The text displayed for this navigation item. Should be short and descriptive (e.g., 'Dashboard', 'Settings', 'Reports').",
70
89
  "order": 1,
71
90
  "type": "string"
72
91
  },
73
92
  "iconName": {
74
93
  "title": "Icon Name",
75
94
  "order": 2,
76
- "description": "Name of the icon from https://fonts.google.com/icons",
95
+ "description": "Material icon name to display alongside the label. Find icon names at https://fonts.google.com/icons (e.g., 'home', 'settings', 'dashboard', 'analytics').",
77
96
  "dataDrivenDisabled": true,
78
97
  "type": "string"
79
98
  },
80
99
  "route": {
81
100
  "title": "Navigation Route",
82
101
  "order": 3,
83
- "description": "Navigation to perform on click. Example: If you are at route /my/route/asset then 'settings/profile' routes to '/my/route/settings/profile'.",
102
+ "description": "The destination path when this item is clicked. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/*/settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.",
84
103
  "type": "string"
85
104
  },
86
- "leadingSlash": {
87
- "title": "Add Leading Slash",
88
- "order": 4,
89
- "description": "Whether to add a leading slash to the navigation route.",
90
- "dataDrivenDisabled": true,
91
- "type": "boolean"
92
- },
93
- "trailingSlash": {
94
- "title": "Add Trailling Slash",
95
- "order": 5,
96
- "description": "Whether to add a trailing slash to the navigation route.",
105
+ "variables": {
106
+ "title": "Navigation Variables",
107
+ "description": "Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.",
108
+ "type": "array",
97
109
  "dataDrivenDisabled": true,
98
- "type": "boolean"
110
+ "order": 4,
111
+ "items": {
112
+ "type": "object",
113
+ "properties": {
114
+ "label": {
115
+ "title": "Label",
116
+ "description": "The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.",
117
+ "type": "string",
118
+ "order": 1
119
+ },
120
+ "value": {
121
+ "title": "Value",
122
+ "description": "The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.",
123
+ "type": "string",
124
+ "order": 2
125
+ }
126
+ }
127
+ }
99
128
  }
100
129
  }
101
130
  }
@@ -73,6 +73,7 @@ export class WidgetNavbar extends LitElement {
73
73
  align-items: end;
74
74
  height: 100%;
75
75
  width: 100%;
76
+ padding: 0 16px;
76
77
  box-sizing: border-box;
77
78
  }
78
79
 
@@ -99,14 +100,28 @@ export class WidgetNavbar extends LitElement {
99
100
  return '/' + route.split('/').filter(Boolean).join('/')
100
101
  }
101
102
 
102
- addSlashes(item?: any): string | undefined {
103
- if (!item.route?.endsWith('/') && item.trailingSlash) {
104
- item.route += '/'
103
+ resolveRoute(item?: any): string | undefined {
104
+ let route = String(item?.route ?? '')
105
+ if (item?.variables) {
106
+ for (const variable of item.variables) {
107
+ if (variable.label) {
108
+ route = route
109
+ .split(`{{${variable.label}}}`)
110
+ .join(encodeURIComponent(String(variable.value ?? '')))
111
+ }
112
+ }
105
113
  }
106
- if (!item.route?.startsWith('/') && item.leadingSlash) {
107
- item.route = '/' + item.route
114
+ if (route.includes('*')) {
115
+ const currentSegments = (this.route || '').split('/').filter(Boolean)
116
+ const routeSegments = route.split('/').filter(Boolean)
117
+ for (let i = 0; i < routeSegments.length; i++) {
118
+ if (routeSegments[i] === '*') {
119
+ routeSegments[i] = currentSegments[i] ?? ''
120
+ }
121
+ }
122
+ route = (route.startsWith('/') ? '/' : '') + routeSegments.filter(Boolean).join('/')
108
123
  }
109
- return item.route
124
+ return route
110
125
  }
111
126
 
112
127
  matchesRoute(itemRoute?: string) {
@@ -136,7 +151,13 @@ export class WidgetNavbar extends LitElement {
136
151
  class="paging"
137
152
  style=${this.inputData?.route ? 'cursor: pointer' : ''}
138
153
  ?active=${this.inputData?.title}
139
- @click=${() => this.handleNavItemClick(this.addSlashes(this.inputData))}
154
+ @click=${() =>
155
+ this.handleNavItemClick(
156
+ this.resolveRoute({
157
+ route: this.inputData?.route,
158
+ variables: this.inputData?.variables
159
+ })
160
+ )}
140
161
  >
141
162
  ${this.inputData?.title}
142
163
  </h2>
@@ -146,11 +167,11 @@ export class WidgetNavbar extends LitElement {
146
167
  (item) => item.label,
147
168
  (item) => html`
148
169
  <md-secondary-tab
149
- ?active=${this.matchesRoute(this.addSlashes(item))}
170
+ ?active=${this.matchesRoute(this.resolveRoute(item))}
150
171
  style="font-size: ${fontSize}px;
151
172
  --md-secondary-tab-container-color: ${bgColor};
152
173
  color: ${fontColor};"
153
- @click=${() => this.handleNavItemClick(this.addSlashes(item))}
174
+ @click=${() => this.handleNavItemClick(this.resolveRoute(item))}
154
175
  >
155
176
  ${item.iconName
156
177
  ? html`