@record-evolution/widget-navbar 1.0.15 → 1.0.17
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/widget-navbar.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LitElement as f, css as
|
|
1
|
+
import { LitElement as f, css as p, nothing as u, html as c } from "lit";
|
|
2
2
|
import { property as d, state as h } from "lit/decorators.js";
|
|
3
3
|
import { repeat as m } from "lit/directives/repeat.js";
|
|
4
4
|
import "@material/web/icon/icon";
|
|
@@ -16,7 +16,7 @@ const g = (s) => {
|
|
|
16
16
|
return e ? parseFloat(e[1]) === 0 : /^#[0-9a-f]{8}$/.test(t) ? t.slice(7) === "00" : /^#[0-9a-f]{4}$/.test(t) ? t[4] === "0" : !1;
|
|
17
17
|
}, v = class v extends f {
|
|
18
18
|
constructor() {
|
|
19
|
-
super(...arguments), this.version = "1.0.
|
|
19
|
+
super(...arguments), this.version = "1.0.17";
|
|
20
20
|
}
|
|
21
21
|
update(t) {
|
|
22
22
|
t.has("theme") && this.registerTheme(this.theme), super.update(t);
|
|
@@ -61,7 +61,7 @@ const g = (s) => {
|
|
|
61
61
|
return t.startsWith("/") ? e.startsWith(a) : e.endsWith(a) || e === a;
|
|
62
62
|
}
|
|
63
63
|
render() {
|
|
64
|
-
const t = this.inputData?.style?.fontSize ?? 16, e = this.inputData?.style?.fontWeight ?? 400, a = t * 1.5, o = this.
|
|
64
|
+
const t = this.inputData?.style?.fontSize ?? 16, e = this.inputData?.style?.fontWeight ?? 400, a = t * 1.5, o = this.themeTitleColor || "black", r = this.themeBgColor || "white";
|
|
65
65
|
return c`
|
|
66
66
|
<div
|
|
67
67
|
class="wrapper"
|
|
@@ -91,7 +91,7 @@ const g = (s) => {
|
|
|
91
91
|
?active=${this.matchesRoute(this.resolveRoute(n))}
|
|
92
92
|
@click=${() => this.handleNavItemClick(this.resolveRoute(n))}
|
|
93
93
|
>
|
|
94
|
-
${n.iconName ? c`<md-icon slot="icon">${n.iconName}</md-icon>` :
|
|
94
|
+
${n.iconName ? c`<md-icon slot="icon">${n.iconName}</md-icon>` : u}
|
|
95
95
|
${n.label}
|
|
96
96
|
</md-secondary-tab>
|
|
97
97
|
`
|
|
@@ -101,7 +101,7 @@ const g = (s) => {
|
|
|
101
101
|
`;
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
|
-
v.styles =
|
|
104
|
+
v.styles = p`
|
|
105
105
|
:host {
|
|
106
106
|
display: block;
|
|
107
107
|
font-family: sans-serif;
|
|
@@ -211,7 +211,7 @@ l([
|
|
|
211
211
|
l([
|
|
212
212
|
h()
|
|
213
213
|
], i.prototype, "themeTitleColor");
|
|
214
|
-
window.customElements.define("widget-navbar-1.0.
|
|
214
|
+
window.customElements.define("widget-navbar-1.0.17", i);
|
|
215
215
|
export {
|
|
216
216
|
i as WidgetNavbar
|
|
217
217
|
};
|
|
@@ -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/secondary-tab'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\n\n/**\n * ECharts themes describe a *chart canvas*, and most of them set\n * `backgroundColor` to a fully transparent colour (the light theme uses\n * `rgba(0, 0, 0, 0)`). That is a valid, truthy colour string, so using it\n * verbatim as the navbar background paints nothing at all. Treat any\n * fully transparent theme colour as \"no colour\" so the fallback kicks in.\n */\nconst isTransparent = (color?: string) => {\n if (!color) return true\n const value = color.trim().toLowerCase()\n if (value === 'transparent') return true\n const functional = value.match(/^(?:rgba|hsla)\\([^)]*[,/]\\s*([\\d.]+%?)\\s*\\)$/)\n if (functional) return parseFloat(functional[1]) === 0\n // #rrggbbaa / #rgba\n if (/^#[0-9a-f]{8}$/.test(value)) return value.slice(7) === '00'\n if (/^#[0-9a-f]{4}$/.test(value)) return value[4] === '0'\n return false\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 const themeBgColor = theme?.theme_object?.backgroundColor\n this.themeBgColor = cssBgColor || (isTransparent(themeBgColor) ? undefined : themeBgColor)\n this.themeTitleColor = cssTextColor || 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 gap: 8px;\n height: 100%;\n width: 100%;\n padding: 0 16px;\n box-sizing: border-box;\n background-color: var(--nav-bg);\n color: var(--nav-fg);\n font-size: var(--nav-font-size);\n font-weight: var(--nav-font-weight);\n }\n\n /* One scrollable row. Without this the tabs wrap onto several lines and\n spill outside the coloured bar as soon as they don't fit. */\n .nav-list {\n display: flex;\n align-items: end;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .nav-list::-webkit-scrollbar {\n display: none;\n }\n\n /* Material's tab tokens default to the M3 palette (purple indicator,\n near-black labels), which ignores the widget's configured colours.\n Map every colour token onto the nav colours. */\n md-secondary-tab {\n flex: none;\n --md-secondary-tab-container-color: var(--nav-bg);\n --md-secondary-tab-label-text-size: var(--nav-font-size);\n --md-secondary-tab-label-text-weight: var(--nav-font-weight);\n --md-secondary-tab-icon-size: var(--nav-icon-size);\n --md-secondary-tab-label-text-color: var(--nav-fg);\n --md-secondary-tab-hover-label-text-color: var(--nav-fg);\n --md-secondary-tab-focus-label-text-color: var(--nav-fg);\n --md-secondary-tab-pressed-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-hover-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-focus-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-label-text-color: var(--nav-fg);\n --md-secondary-tab-icon-color: var(--nav-fg);\n --md-secondary-tab-hover-icon-color: var(--nav-fg);\n --md-secondary-tab-focus-icon-color: var(--nav-fg);\n --md-secondary-tab-pressed-icon-color: var(--nav-fg);\n --md-secondary-tab-active-icon-color: var(--nav-fg);\n --md-secondary-tab-active-hover-icon-color: var(--nav-fg);\n --md-secondary-tab-active-focus-icon-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-icon-color: var(--nav-fg);\n --md-secondary-tab-active-indicator-color: var(--nav-fg);\n --md-secondary-tab-hover-state-layer-color: var(--nav-fg);\n --md-secondary-tab-pressed-state-layer-color: var(--nav-fg);\n --md-secondary-tab-active-hover-state-layer-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-state-layer-color: var(--nav-fg);\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n font-size: var(--nav-icon-size);\n width: var(--nav-icon-size);\n height: var(--nav-icon-size);\n color: var(--nav-fg);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\n flex: none;\n display: flex;\n align-items: center;\n min-height: 48px;\n font-size: 1.2em;\n /* the UA stylesheet forces bold, which would ignore the\n configured font weight */\n font-weight: inherit;\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 fontWeight = this.inputData?.style?.fontWeight ?? 400\n const iconFontSize = fontSize * 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=\"--nav-bg: ${bgColor}; --nav-fg: ${fontColor};\n --nav-font-size: ${fontSize}px; --nav-font-weight: ${fontWeight};\n --nav-icon-size: ${iconFontSize}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 <div class=\"nav-list\" role=\"tablist\">\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 @click=${() => this.handleNavItemClick(this.resolveRoute(item))}\n >\n ${item.iconName\n ? html`<md-icon slot=\"icon\">${item.iconName}</md-icon>`\n : nothing}\n ${item.label}\n </md-secondary-tab>\n `\n )}\n </div>\n </div>\n `\n }\n}\nwindow.customElements.define('widget-navbar-versionplaceholder', WidgetNavbar)\n"],"names":["isTransparent","color","value","functional","_WidgetNavbar","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","themeBgColor","route","event","item","variable","currentSegments","routeSegments","i","itemRoute","subRoute","fontSize","fontWeight","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 { NavigationBarConfiguration } from './definition-schema'\n\nimport '@material/web/icon/icon'\nimport '@material/web/tabs/secondary-tab'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\n\n/**\n * ECharts themes describe a *chart canvas*, and most of them set\n * `backgroundColor` to a fully transparent colour (the light theme uses\n * `rgba(0, 0, 0, 0)`). That is a valid, truthy colour string, so using it\n * verbatim as the navbar background paints nothing at all. Treat any\n * fully transparent theme colour as \"no colour\" so the fallback kicks in.\n */\nconst isTransparent = (color?: string) => {\n if (!color) return true\n const value = color.trim().toLowerCase()\n if (value === 'transparent') return true\n const functional = value.match(/^(?:rgba|hsla)\\([^)]*[,/]\\s*([\\d.]+%?)\\s*\\)$/)\n if (functional) return parseFloat(functional[1]) === 0\n // #rrggbbaa / #rgba\n if (/^#[0-9a-f]{8}$/.test(value)) return value.slice(7) === '00'\n if (/^#[0-9a-f]{4}$/.test(value)) return value[4] === '0'\n return false\n}\nexport class WidgetNavbar extends LitElement {\n @property({ type: Object }) inputData?: NavigationBarConfiguration\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 const themeBgColor = theme?.theme_object?.backgroundColor\n this.themeBgColor = cssBgColor || (isTransparent(themeBgColor) ? undefined : themeBgColor)\n this.themeTitleColor = cssTextColor || 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 gap: 8px;\n height: 100%;\n width: 100%;\n padding: 0 16px;\n box-sizing: border-box;\n background-color: var(--nav-bg);\n color: var(--nav-fg);\n font-size: var(--nav-font-size);\n font-weight: var(--nav-font-weight);\n }\n\n /* One scrollable row. Without this the tabs wrap onto several lines and\n spill outside the coloured bar as soon as they don't fit. */\n .nav-list {\n display: flex;\n align-items: end;\n flex: 1;\n min-width: 0;\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .nav-list::-webkit-scrollbar {\n display: none;\n }\n\n /* Material's tab tokens default to the M3 palette (purple indicator,\n near-black labels), which ignores the widget's configured colours.\n Map every colour token onto the nav colours. */\n md-secondary-tab {\n flex: none;\n --md-secondary-tab-container-color: var(--nav-bg);\n --md-secondary-tab-label-text-size: var(--nav-font-size);\n --md-secondary-tab-label-text-weight: var(--nav-font-weight);\n --md-secondary-tab-icon-size: var(--nav-icon-size);\n --md-secondary-tab-label-text-color: var(--nav-fg);\n --md-secondary-tab-hover-label-text-color: var(--nav-fg);\n --md-secondary-tab-focus-label-text-color: var(--nav-fg);\n --md-secondary-tab-pressed-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-hover-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-focus-label-text-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-label-text-color: var(--nav-fg);\n --md-secondary-tab-icon-color: var(--nav-fg);\n --md-secondary-tab-hover-icon-color: var(--nav-fg);\n --md-secondary-tab-focus-icon-color: var(--nav-fg);\n --md-secondary-tab-pressed-icon-color: var(--nav-fg);\n --md-secondary-tab-active-icon-color: var(--nav-fg);\n --md-secondary-tab-active-hover-icon-color: var(--nav-fg);\n --md-secondary-tab-active-focus-icon-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-icon-color: var(--nav-fg);\n --md-secondary-tab-active-indicator-color: var(--nav-fg);\n --md-secondary-tab-hover-state-layer-color: var(--nav-fg);\n --md-secondary-tab-pressed-state-layer-color: var(--nav-fg);\n --md-secondary-tab-active-hover-state-layer-color: var(--nav-fg);\n --md-secondary-tab-active-pressed-state-layer-color: var(--nav-fg);\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n font-size: var(--nav-icon-size);\n width: var(--nav-icon-size);\n height: var(--nav-icon-size);\n color: var(--nav-fg);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\n flex: none;\n display: flex;\n align-items: center;\n min-height: 48px;\n font-size: 1.2em;\n /* the UA stylesheet forces bold, which would ignore the\n configured font weight */\n font-weight: inherit;\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 fontWeight = this.inputData?.style?.fontWeight ?? 400\n const iconFontSize = fontSize * 1.5\n const fontColor = this.themeTitleColor || 'black'\n const bgColor = this.themeBgColor || 'white'\n return html`\n <div\n class=\"wrapper\"\n style=\"--nav-bg: ${bgColor}; --nav-fg: ${fontColor};\n --nav-font-size: ${fontSize}px; --nav-font-weight: ${fontWeight};\n --nav-icon-size: ${iconFontSize}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 <div class=\"nav-list\" role=\"tablist\">\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 @click=${() => this.handleNavItemClick(this.resolveRoute(item))}\n >\n ${item.iconName\n ? html`<md-icon slot=\"icon\">${item.iconName}</md-icon>`\n : nothing}\n ${item.label}\n </md-secondary-tab>\n `\n )}\n </div>\n </div>\n `\n }\n}\nwindow.customElements.define('widget-navbar-versionplaceholder', WidgetNavbar)\n"],"names":["isTransparent","color","value","functional","_WidgetNavbar","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","themeBgColor","route","event","item","variable","currentSegments","routeSegments","i","itemRoute","subRoute","fontSize","fontWeight","iconFontSize","fontColor","bgColor","html","repeat","nothing","css","WidgetNavbar","__decorateClass","property","state"],"mappings":";;;;;;;;;;AAoBA,MAAMA,IAAgB,CAACC,MAAmB;AACtC,MAAI,CAACA,EAAO,QAAO;AACnB,QAAMC,IAAQD,EAAM,KAAA,EAAO,YAAA;AAC3B,MAAIC,MAAU,cAAe,QAAO;AACpC,QAAMC,IAAaD,EAAM,MAAM,8CAA8C;AAC7E,SAAIC,IAAmB,WAAWA,EAAW,CAAC,CAAC,MAAM,IAEjD,iBAAiB,KAAKD,CAAK,IAAUA,EAAM,MAAM,CAAC,MAAM,OACxD,iBAAiB,KAAKA,CAAK,IAAUA,EAAM,CAAC,MAAM,MAC/C;AACX,GACaE,IAAN,MAAMA,UAAqBC,EAAW;AAAA,EAAtC,cAAA;AAAA,UAAA,GAAA,SAAA,GAQH,KAAA,UAAkB;AAAA,EAAA;AAAA,EAElB,OAAOC,GAAqC;AACxC,IAAIA,EAAkB,IAAI,OAAO,KAC7B,KAAK,cAAc,KAAK,KAAK,GAGjC,MAAM,OAAOA,CAAiB;AAAA,EAClC;AAAA,EAEU,aAAaC,GAA0C;AAC7D,SAAK,cAAc,KAAK,KAAK;AAAA,EACjC;AAAA,EAEA,cAAcC,GAAe;AACzB,UAAMC,IAAe,iBAAiB,IAAI,EAAE,iBAAiB,iBAAiB,EAAE,KAAA,GAC1EC,IAAa,iBAAiB,IAAI,EAAE,iBAAiB,4BAA4B,EAAE,KAAA,GACnFC,IAAeH,GAAO,cAAc;AAC1C,SAAK,eAAeE,MAAeV,EAAcW,CAAY,IAAI,SAAYA,IAC7E,KAAK,kBAAkBF,KAAgBD,GAAO,cAAc,OAAO,WAAW;AAAA,EAClF;AAAA,EAEA,mBAAmBI,GAAgB;AAE/B,UAAMC,IAAQ,IAAI,YAAY,cAAc;AAAA,MACxC,QAAQ,EAAE,MAAMD,EAAA;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,IAAA,CACb;AACD,SAAK,cAAcC,CAAK;AAAA,EAC5B;AAAA,EAEA,eAAeD,GAAgB;AAC3B,WAAKA,KAAc;AAAA,EAEvB;AAAA,EAiGA,UAAUA,GAAgB;AACtB,WAAKA,IACE,MAAMA,EAAM,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,IADnC;AAAA,EAEvB;AAAA,EAEA,aAAaE,GAAgC;AACzC,QAAIF,IAAQ,OAAOE,GAAM,SAAS,EAAE;AACpC,QAAIA,GAAM;AACN,iBAAWC,KAAYD,EAAK;AACxB,QAAIC,EAAS,UACTH,IAAQA,EACH,MAAM,KAAKG,EAAS,KAAK,IAAI,EAC7B,KAAK,mBAAmB,OAAOA,EAAS,SAAS,EAAE,CAAC,CAAC;AAItE,QAAIH,EAAM,SAAS,GAAG,GAAG;AACrB,YAAMI,KAAmB,KAAK,SAAS,IAAI,MAAM,GAAG,EAAE,OAAO,OAAO,GAC9DC,IAAgBL,EAAM,MAAM,GAAG,EAAE,OAAO,OAAO;AACrD,eAASM,IAAI,GAAGA,IAAID,EAAc,QAAQC;AACtC,QAAID,EAAcC,CAAC,MAAM,QACrBD,EAAcC,CAAC,IAAIF,EAAgBE,CAAC,KAAK;AAGjD,MAAAN,KAASA,EAAM,WAAW,GAAG,IAAI,MAAM,MAAMK,EAAc,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,IACvF;AACA,WAAOL;AAAA,EACX;AAAA,EAEA,aAAaO,GAAoB;AAC7B,QAAIA,MAAc,OAAW,QAAO;AACpC,UAAMP,IAAQ,KAAK,UAAU,mBAAmB,KAAK,SAAS,GAAG,CAAC,GAC5DQ,IAAW,KAAK,UAAUD,CAAS;AACzC,WAAIA,EAAU,WAAW,GAAG,IACjBP,EAAM,WAAWQ,CAAQ,IAEzBR,EAAM,SAASQ,CAAQ,KAAKR,MAAUQ;AAAA,EAErD;AAAA,EAEA,SAAS;AACL,UAAMC,IAAW,KAAK,WAAW,OAAO,YAAY,IAC9CC,IAAa,KAAK,WAAW,OAAO,cAAc,KAClDC,IAAeF,IAAW,KAC1BG,IAAY,KAAK,mBAAmB,SACpCC,IAAU,KAAK,gBAAgB;AACrC,WAAOC;AAAA;AAAA;AAAA,mCAGoBD,CAAO,eAAeD,CAAS;AAAA,mCAC/BH,CAAQ,0BAA0BC,CAAU;AAAA,mCAC5CC,CAAY;AAAA;AAAA;AAAA;AAAA,4BAInB,KAAK,WAAW,QAAQ,oBAAoB,EAAE;AAAA,8BAC5C,KAAK,WAAW,KAAK;AAAA,6BACtB,MACL,KAAK;AAAA,MACD,KAAK,aAAa;AAAA,QACd,OAAO,KAAK,WAAW;AAAA,QACvB,WAAW,KAAK,WAAW;AAAA,MAAA,CAC9B;AAAA,IAAA,CACJ;AAAA;AAAA,sBAEH,KAAK,WAAW,KAAK;AAAA;AAAA;AAAA,sBAGrBI;AAAA,MACE,KAAK,WAAW,YAAY,CAAA;AAAA,MAC5B,CAACb,MAASA,EAAK;AAAA,MACf,CAACA,MAASY;AAAA;AAAA,0CAEQ,KAAK,aAAa,KAAK,aAAaZ,CAAI,CAAC,CAAC;AAAA,yCAC3C,MAAM,KAAK,mBAAmB,KAAK,aAAaA,CAAI,CAAC,CAAC;AAAA;AAAA,kCAE7DA,EAAK,WACDY,yBAA4BZ,EAAK,QAAQ,eACzCc,CAAO;AAAA,kCACXd,EAAK,KAAK;AAAA;AAAA;AAAA,IAAA,CAGvB;AAAA;AAAA;AAAA;AAAA,EAIjB;AACJ;AAtLIV,EAAO,SAASyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA7Cb,IAAMC,IAAN1B;AACyB2B,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GADjBF,EACmB,WAAA,WAAA;AACAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAFjBF,EAEmB,WAAA,OAAA;AACAC,EAAA;AAAA,EAA3BC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAHjBF,EAGmB,WAAA,OAAA;AAEXC,EAAA;AAAA,EAAhBE,EAAA;AAAM,GALEH,EAKQ,WAAA,cAAA;AACAC,EAAA;AAAA,EAAhBE,EAAA;AAAM,GANEH,EAMQ,WAAA,iBAAA;AA8NrB,OAAO,eAAe,OAAO,wBAAoCA,CAAY;"}
|
package/package.json
CHANGED
|
@@ -77,9 +77,9 @@ export type NavigationItems = {
|
|
|
77
77
|
}[];
|
|
78
78
|
|
|
79
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
|
|
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 font size and weight; colors follow the dashboard theme or the widget's custom tile style. Ideal for multi-page dashboards requiring clear navigation structure and branding.
|
|
81
81
|
*/
|
|
82
|
-
export interface
|
|
82
|
+
export interface NavigationBarConfiguration {
|
|
83
83
|
title?: TitleSettings;
|
|
84
84
|
route?: TitleNavigation;
|
|
85
85
|
variables?: TitleNavigationVariables;
|
|
@@ -93,19 +93,5 @@ export interface InputData {
|
|
|
93
93
|
export interface ItemStyle {
|
|
94
94
|
fontSize?: FontSize;
|
|
95
95
|
fontWeight?: FontWeight;
|
|
96
|
-
color?: FontColor;
|
|
97
|
-
backgroundColor?: BackgroundColor;
|
|
98
|
-
[k: string]: unknown;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Text color for navigation item labels.
|
|
102
|
-
*/
|
|
103
|
-
export interface FontColor {
|
|
104
|
-
[k: string]: unknown;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Background color of the navigation bar.
|
|
108
|
-
*/
|
|
109
|
-
export interface BackgroundColor {
|
|
110
96
|
[k: string]: unknown;
|
|
111
97
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"title": "
|
|
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
|
|
2
|
+
"title": "Navigation Bar Configuration",
|
|
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 font size and weight; colors follow the dashboard theme or the widget's custom tile style. Ideal for multi-page dashboards requiring clear navigation structure and branding.",
|
|
4
|
+
"aiSelection": {
|
|
5
|
+
"dataShape": "Navigation structure only: a title with a route, plus navItems[] each carrying a label, an icon and a route. No data input.",
|
|
6
|
+
"useWhen": [
|
|
7
|
+
"A multi-page dashboard needs consistent top-level navigation across its pages.",
|
|
8
|
+
"A header combining branding (the title) with links to the main sections is wanted.",
|
|
9
|
+
"Route parameters should be carried along per item (variables[])."
|
|
10
|
+
],
|
|
11
|
+
"notFor": [
|
|
12
|
+
"Navigation down the side of the page — use widget-sidenav.",
|
|
13
|
+
"A single link or call to action — use widget-navbutton.",
|
|
14
|
+
"Switching what data the page shows rather than which page is shown — that is filtering. Use widget-filter-dropdown.",
|
|
15
|
+
"A heading that is only text and does not navigate — use widget-label."
|
|
16
|
+
]
|
|
17
|
+
},
|
|
4
18
|
"type": "object",
|
|
5
19
|
"properties": {
|
|
6
20
|
"title": {
|
|
@@ -58,20 +72,6 @@
|
|
|
58
72
|
"order": 3,
|
|
59
73
|
"dataDrivenDisabled": true,
|
|
60
74
|
"type": "number"
|
|
61
|
-
},
|
|
62
|
-
"color": {
|
|
63
|
-
"title": "Font Color",
|
|
64
|
-
"description": "Text color for navigation item labels.",
|
|
65
|
-
"order": 4,
|
|
66
|
-
"type": "color",
|
|
67
|
-
"dataDrivenDisabled": true
|
|
68
|
-
},
|
|
69
|
-
"backgroundColor": {
|
|
70
|
-
"title": "Background Color",
|
|
71
|
-
"description": "Background color of the navigation bar.",
|
|
72
|
-
"order": 5,
|
|
73
|
-
"type": "color",
|
|
74
|
-
"dataDrivenDisabled": true
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
},
|
package/src/widget-navbar.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { html, css, LitElement, PropertyValues, nothing } from 'lit'
|
|
2
2
|
import { property, state } from 'lit/decorators.js'
|
|
3
3
|
import { repeat } from 'lit/directives/repeat.js'
|
|
4
|
-
import {
|
|
4
|
+
import { NavigationBarConfiguration } from './definition-schema'
|
|
5
5
|
|
|
6
6
|
import '@material/web/icon/icon'
|
|
7
7
|
import '@material/web/tabs/secondary-tab'
|
|
@@ -30,7 +30,7 @@ const isTransparent = (color?: string) => {
|
|
|
30
30
|
return false
|
|
31
31
|
}
|
|
32
32
|
export class WidgetNavbar extends LitElement {
|
|
33
|
-
@property({ type: Object }) inputData?:
|
|
33
|
+
@property({ type: Object }) inputData?: NavigationBarConfiguration
|
|
34
34
|
@property({ type: Object }) theme?: Theme
|
|
35
35
|
@property({ type: String }) route?: string
|
|
36
36
|
|
|
@@ -213,8 +213,8 @@ export class WidgetNavbar extends LitElement {
|
|
|
213
213
|
const fontSize = this.inputData?.style?.fontSize ?? 16
|
|
214
214
|
const fontWeight = this.inputData?.style?.fontWeight ?? 400
|
|
215
215
|
const iconFontSize = fontSize * 1.5
|
|
216
|
-
const fontColor = this.
|
|
217
|
-
const bgColor = this.
|
|
216
|
+
const fontColor = this.themeTitleColor || 'black'
|
|
217
|
+
const bgColor = this.themeBgColor || 'white'
|
|
218
218
|
return html`
|
|
219
219
|
<div
|
|
220
220
|
class="wrapper"
|