@record-evolution/widget-sidenav 1.0.17 → 1.0.19

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/README.md CHANGED
@@ -29,7 +29,7 @@ npm i @record-evolution/widget-sidenav
29
29
  The widget accepts an `inputData` property with the following structure:
30
30
 
31
31
  ```typescript
32
- interface InputData {
32
+ interface SideNavigationConfiguration {
33
33
  title?: string
34
34
  route?: string // Navigation route for title click
35
35
  leadingSlash?: boolean // Add leading slash to routes
@@ -1,11 +1,11 @@
1
1
  import { css as u, LitElement as d, html as c } from "lit";
2
- import { property as h, state as p, customElement as g } from "lit/decorators.js";
2
+ import { property as h, state as p, customElement as b } from "lit/decorators.js";
3
3
  import { repeat as m } from "lit/directives/repeat.js";
4
4
  import "@material/web/icon/icon.js";
5
- var b = Object.defineProperty, f = Object.getOwnPropertyDescriptor, l = (t, e, r, i) => {
6
- for (var o = i > 1 ? void 0 : i ? f(e, r) : e, a = t.length - 1, s; a >= 0; a--)
7
- (s = t[a]) && (o = (i ? s(e, r, o) : s(o)) || o);
8
- return i && o && b(e, r, o), o;
5
+ var f = Object.defineProperty, g = Object.getOwnPropertyDescriptor, a = (t, e, r, i) => {
6
+ for (var o = i > 1 ? void 0 : i ? g(e, r) : e, l = t.length - 1, s; l >= 0; l--)
7
+ (s = t[l]) && (o = (i ? s(e, r, o) : s(o)) || o);
8
+ return i && o && f(e, r, o), o;
9
9
  };
10
10
  const v = (t) => {
11
11
  if (!t) return !0;
@@ -16,7 +16,7 @@ const v = (t) => {
16
16
  };
17
17
  let n = class extends d {
18
18
  constructor() {
19
- super(...arguments), this.version = "1.0.17";
19
+ super(...arguments), this.version = "1.0.19";
20
20
  }
21
21
  update(t) {
22
22
  t.has("theme") && this.registerTheme(this.theme), super.update(t);
@@ -25,8 +25,8 @@ let n = class extends d {
25
25
  this.registerTheme(this.theme);
26
26
  }
27
27
  registerTheme(t) {
28
- const e = getComputedStyle(this).getPropertyValue("--re-text-color").trim(), r = getComputedStyle(this).getPropertyValue("--re-tile-background-color").trim(), i = t?.theme_object?.backgroundColor;
29
- this.themeBgColor = r || (v(i) ? void 0 : i), this.themeTitleColor = e || t?.theme_object?.title?.textStyle?.color;
28
+ const e = t?.theme_object?.backgroundColor;
29
+ this.themeBgColor = `var(--re-tile-background-color, ${(v(e) ? void 0 : e) || "transparent"})`, this.themeTitleColor = `var(--re-text-color, ${t?.theme_object?.title?.textStyle?.color || "inherit"})`;
30
30
  }
31
31
  handleNavItemClick(t) {
32
32
  const e = new CustomEvent("nav-submit", {
@@ -59,7 +59,7 @@ let n = class extends d {
59
59
  return t.startsWith("/") ? e.startsWith(r) : e.endsWith(r) || e === r;
60
60
  }
61
61
  render() {
62
- const t = this.inputData?.style?.fontSize ?? 16, e = this.inputData?.style?.fontWeight ?? 400, r = t * 1.5, i = this.inputData?.style?.color || this.themeTitleColor || "black", o = this.inputData?.style?.backgroundColor || this.themeBgColor || "white", a = t * 0.4;
62
+ const t = this.inputData?.style?.fontSize ?? 16, e = this.inputData?.style?.fontWeight ?? 400, r = t * 1.5, i = this.inputData?.style?.color || this.themeTitleColor || "black", o = this.inputData?.style?.backgroundColor || this.themeBgColor || "white", l = t * 0.4;
63
63
  return c`
64
64
  <div
65
65
  class="wrapper"
@@ -87,7 +87,7 @@ let n = class extends d {
87
87
  (s) => c`
88
88
  <div
89
89
  class="nav-item ${this.matchesRoute(this.resolveRoute(s)) ? "selected" : ""}"
90
- style="gap: ${a}px;"
90
+ style="gap: ${l}px;"
91
91
  @click=${() => this.handleNavItemClick(this.resolveRoute(s))}
92
92
  >
93
93
  ${s.iconName ? c`
@@ -185,23 +185,23 @@ n.styles = u`
185
185
  font-weight: inherit;
186
186
  }
187
187
  `;
188
- l([
188
+ a([
189
189
  h({ type: Object })
190
190
  ], n.prototype, "inputData", 2);
191
- l([
191
+ a([
192
192
  h({ type: Object })
193
193
  ], n.prototype, "theme", 2);
194
- l([
194
+ a([
195
195
  h({ type: String })
196
196
  ], n.prototype, "route", 2);
197
- l([
197
+ a([
198
198
  p()
199
199
  ], n.prototype, "themeBgColor", 2);
200
- l([
200
+ a([
201
201
  p()
202
202
  ], n.prototype, "themeTitleColor", 2);
203
- n = l([
204
- g("widget-sidenav-1.0.17")
203
+ n = a([
204
+ b("widget-sidenav-1.0.19")
205
205
  ], n);
206
206
  export {
207
207
  n as WidgetSidenav
@@ -1 +1 @@
1
- {"version":3,"file":"widget-sidenav.js","sources":["../src/widget-sidenav.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { InputData } from './definition-schema'\n\nimport '@material/web/icon/icon.js'\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 nav 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}\n\n@customElement('widget-sidenav-versionplaceholder')\nexport class WidgetSidenav 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: String(route) },\n bubbles: true,\n composed: true\n })\n this.dispatchEvent(event)\n }\n\n trimRoute(route?: string) {\n route = String(route)\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 itemRoute = String(itemRoute)\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 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 flex-direction: column;\n height: 100%;\n width: 100%;\n padding: 12px;\n box-sizing: border-box;\n }\n\n .nav-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 12px;\n overflow-y: auto;\n flex-grow: 1;\n /* Derive scrollbar colors from the (inherited) text color so they\n follow custom styles and themes — e.g. light thumb on dark nav. */\n scrollbar-width: thin;\n scrollbar-color: color-mix(in srgb, currentColor 35%, transparent) transparent;\n }\n\n /* WebKit/Blink fallback for browsers without scrollbar-color support. */\n .nav-list::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n .nav-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .nav-list::-webkit-scrollbar-thumb {\n background-color: color-mix(in srgb, currentColor 35%, transparent);\n border-radius: 4px;\n }\n\n .nav-list::-webkit-scrollbar-thumb:hover {\n background-color: color-mix(in srgb, currentColor 55%, transparent);\n }\n\n .nav-item {\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border-radius: 4px;\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n }\n\n /* Derive the highlight from the (inherited) text color, like the\n scrollbar above — a fixed black wash is invisible on a dark nav. */\n .selected {\n background-color: color-mix(in srgb, currentColor 15%, transparent);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\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 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 const gap = fontSize * 0.4\n return html`\n <div\n class=\"wrapper\"\n style=\"background-color: ${bgColor}; color: ${fontColor};\n font-weight: ${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 <div class=\"nav-list\">\n ${repeat(\n this.inputData?.navItems || [],\n (item) => item.label,\n (item) => html`\n <div\n class=\"nav-item ${this.matchesRoute(this.resolveRoute(item))\n ? 'selected'\n : ''}\"\n style=\"gap: ${gap}px;\"\n @click=${() => this.handleNavItemClick(this.resolveRoute(item))}\n >\n ${item.iconName\n ? html`\n <md-icon style=\"--md-icon-size: ${iconFontSize}px;\"\n >${item.iconName}\n </md-icon>\n `\n : ''}\n ${item.label}\n </div>\n `\n )}\n </div>\n </div>\n `\n }\n}\n"],"names":["isTransparent","color","value","functional","WidgetSidenav","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","themeBgColor","route","event","item","variable","currentSegments","routeSegments","i","itemRoute","subRoute","fontSize","fontWeight","iconFontSize","fontColor","bgColor","gap","html","repeat","css","__decorateClass","property","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"widget-sidenav.js","sources":["../src/widget-sidenav.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { SideNavigationConfiguration } from './definition-schema'\n\nimport '@material/web/icon/icon.js'\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 nav 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}\n\n@customElement('widget-sidenav-versionplaceholder')\nexport class WidgetSidenav extends LitElement {\n @property({ type: Object }) inputData?: SideNavigationConfiguration\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 themeBgColor = theme?.theme_object?.backgroundColor\n this.themeBgColor = `var(--re-tile-background-color, ${(isTransparent(themeBgColor) ? undefined : themeBgColor) || 'transparent'})`\n this.themeTitleColor = `var(--re-text-color, ${theme?.theme_object?.title?.textStyle?.color || 'inherit'})`\n }\n\n handleNavItemClick(route?: string) {\n // console.log('Navigating to:', item.route)\n const event = new CustomEvent('nav-submit', {\n detail: { path: String(route) },\n bubbles: true,\n composed: true\n })\n this.dispatchEvent(event)\n }\n\n trimRoute(route?: string) {\n route = String(route)\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 itemRoute = String(itemRoute)\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 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 flex-direction: column;\n height: 100%;\n width: 100%;\n padding: 12px;\n box-sizing: border-box;\n }\n\n .nav-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 12px;\n overflow-y: auto;\n flex-grow: 1;\n /* Derive scrollbar colors from the (inherited) text color so they\n follow custom styles and themes — e.g. light thumb on dark nav. */\n scrollbar-width: thin;\n scrollbar-color: color-mix(in srgb, currentColor 35%, transparent) transparent;\n }\n\n /* WebKit/Blink fallback for browsers without scrollbar-color support. */\n .nav-list::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n .nav-list::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .nav-list::-webkit-scrollbar-thumb {\n background-color: color-mix(in srgb, currentColor 35%, transparent);\n border-radius: 4px;\n }\n\n .nav-list::-webkit-scrollbar-thumb:hover {\n background-color: color-mix(in srgb, currentColor 55%, transparent);\n }\n\n .nav-item {\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border-radius: 4px;\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n }\n\n /* Derive the highlight from the (inherited) text color, like the\n scrollbar above — a fixed black wash is invisible on a dark nav. */\n .selected {\n background-color: color-mix(in srgb, currentColor 15%, transparent);\n }\n\n h2 {\n margin: 0;\n padding: 0px;\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 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 const gap = fontSize * 0.4\n return html`\n <div\n class=\"wrapper\"\n style=\"background-color: ${bgColor}; color: ${fontColor};\n font-weight: ${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 <div class=\"nav-list\">\n ${repeat(\n this.inputData?.navItems || [],\n (item) => item.label,\n (item) => html`\n <div\n class=\"nav-item ${this.matchesRoute(this.resolveRoute(item))\n ? 'selected'\n : ''}\"\n style=\"gap: ${gap}px;\"\n @click=${() => this.handleNavItemClick(this.resolveRoute(item))}\n >\n ${item.iconName\n ? html`\n <md-icon style=\"--md-icon-size: ${iconFontSize}px;\"\n >${item.iconName}\n </md-icon>\n `\n : ''}\n ${item.label}\n </div>\n `\n )}\n </div>\n </div>\n `\n }\n}\n"],"names":["isTransparent","color","value","functional","WidgetSidenav","LitElement","changedProperties","_changedProperties","theme","themeBgColor","route","event","item","variable","currentSegments","routeSegments","i","itemRoute","subRoute","fontSize","fontWeight","iconFontSize","fontColor","bgColor","gap","html","repeat","css","__decorateClass","property","state","customElement"],"mappings":"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"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent widget-sidenav following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "widget-sidenav",
6
- "version": "1.0.17",
6
+ "version": "1.0.19",
7
7
  "engines": {
8
8
  "node": ">=24.9.0",
9
9
  "npm": ">=10.0.2"
@@ -25,7 +25,11 @@
25
25
  "link": "npm run build && npm link && cd ../RESWARM/frontend && npm link @record-evolution/widget-sidenav",
26
26
  "unlink": "npm unlink --global && cd ../RESWARM/frontend && npm unlink @record-evolution/widget-sidenav && npm i @record-evolution/widget-sidenav",
27
27
  "types": "cat src/definition-schema.json | json2ts --style.tabWidth=4 > src/definition-schema.d.ts",
28
- "release": "npm run build && npm run types && npm version patch --tag-version-prefix='' && git push && git push --tag && npm run build"
28
+ "preversion": "sh scripts/release-preflight.sh",
29
+ "postversion": "git push --follow-tags && sh scripts/release-verify.sh",
30
+ "release": "npm version patch",
31
+ "release:minor": "npm version minor",
32
+ "release:major": "npm version major"
29
33
  },
30
34
  "dependencies": {
31
35
  "lit": "^3.3.3",
@@ -79,7 +79,7 @@ export type NavigationItems = {
79
79
  /**
80
80
  * A vertical side navigation widget for creating sidebar menus in dashboards. Use this widget to provide hierarchical or list-based navigation along the side of the dashboard. Features a clickable title/header and multiple navigation items with icons. Supports customizable styling for fonts and colors to match your dashboard theme. Ideal for applications with multiple sections, settings pages, or when you need persistent navigation that doesn't take up header space.
81
81
  */
82
- export interface InputData {
82
+ export interface SideNavigationConfiguration {
83
83
  title?: TitleSettings;
84
84
  route?: TitleNavigation;
85
85
  variables?: TitleNavigationVariables;
@@ -1,6 +1,20 @@
1
1
  {
2
- "title": "Input Data",
2
+ "title": "Side Navigation Configuration",
3
3
  "description": "A vertical side navigation widget for creating sidebar menus in dashboards. Use this widget to provide hierarchical or list-based navigation along the side of the dashboard. Features a clickable title/header and multiple navigation items with icons. Supports customizable styling for fonts and colors to match your dashboard theme. Ideal for applications with multiple sections, settings pages, or when you need persistent navigation that doesn't take up header space.",
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 dashboard has enough sections to need a persistent menu that does not consume header height.",
8
+ "Navigation should sit down the side, list-style, alongside the content.",
9
+ "An application-like layout with settings or sub-sections is being built."
10
+ ],
11
+ "notFor": [
12
+ "Navigation across the top of the page — use widget-navbar.",
13
+ "A single link or button — use widget-navbutton.",
14
+ "Choosing which data is shown rather than which page — 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": {
@@ -1,7 +1,7 @@
1
1
  import { html, css, LitElement, PropertyValues } from 'lit'
2
2
  import { customElement, property, state } from 'lit/decorators.js'
3
3
  import { repeat } from 'lit/directives/repeat.js'
4
- import { InputData } from './definition-schema'
4
+ import { SideNavigationConfiguration } from './definition-schema'
5
5
 
6
6
  import '@material/web/icon/icon.js'
7
7
 
@@ -31,7 +31,7 @@ const isTransparent = (color?: string) => {
31
31
 
32
32
  @customElement('widget-sidenav-versionplaceholder')
33
33
  export class WidgetSidenav extends LitElement {
34
- @property({ type: Object }) inputData?: InputData
34
+ @property({ type: Object }) inputData?: SideNavigationConfiguration
35
35
  @property({ type: Object }) theme?: Theme
36
36
  @property({ type: String }) route?: string
37
37
 
@@ -53,11 +53,9 @@ export class WidgetSidenav extends LitElement {
53
53
  }
54
54
 
55
55
  registerTheme(theme?: Theme) {
56
- const cssTextColor = getComputedStyle(this).getPropertyValue('--re-text-color').trim()
57
- const cssBgColor = getComputedStyle(this).getPropertyValue('--re-tile-background-color').trim()
58
56
  const themeBgColor = theme?.theme_object?.backgroundColor
59
- this.themeBgColor = cssBgColor || (isTransparent(themeBgColor) ? undefined : themeBgColor)
60
- this.themeTitleColor = cssTextColor || theme?.theme_object?.title?.textStyle?.color
57
+ this.themeBgColor = `var(--re-tile-background-color, ${(isTransparent(themeBgColor) ? undefined : themeBgColor) || 'transparent'})`
58
+ this.themeTitleColor = `var(--re-text-color, ${theme?.theme_object?.title?.textStyle?.color || 'inherit'})`
61
59
  }
62
60
 
63
61
  handleNavItemClick(route?: string) {