@record-evolution/widget-sidenav 1.0.16 → 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.
@@ -1,15 +1,22 @@
1
1
  import { css as u, LitElement as d, html as c } from "lit";
2
- import { property as p, state as h, customElement as m } from "lit/decorators.js";
3
- import { repeat as b } from "lit/directives/repeat.js";
2
+ import { property as h, state as p, customElement as g } from "lit/decorators.js";
3
+ import { repeat as m } from "lit/directives/repeat.js";
4
4
  import "@material/web/icon/icon.js";
5
- var g = Object.defineProperty, f = Object.getOwnPropertyDescriptor, l = (t, e, r, o) => {
6
- for (var i = o > 1 ? void 0 : o ? f(e, r) : e, n = t.length - 1, a; n >= 0; n--)
7
- (a = t[n]) && (i = (o ? a(e, r, i) : a(i)) || i);
8
- return o && i && g(e, r, i), i;
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;
9
9
  };
10
- let s = class extends d {
10
+ const v = (t) => {
11
+ if (!t) return !0;
12
+ const e = t.trim().toLowerCase();
13
+ if (e === "transparent") return !0;
14
+ const r = e.match(/^(?:rgba|hsla)\([^)]*[,/]\s*([\d.]+%?)\s*\)$/);
15
+ return r ? parseFloat(r[1]) === 0 : /^#[0-9a-f]{8}$/.test(e) ? e.slice(7) === "00" : /^#[0-9a-f]{4}$/.test(e) ? e[4] === "0" : !1;
16
+ };
17
+ let n = class extends d {
11
18
  constructor() {
12
- super(...arguments), this.version = "1.0.16";
19
+ super(...arguments), this.version = "1.0.17";
13
20
  }
14
21
  update(t) {
15
22
  t.has("theme") && this.registerTheme(this.theme), super.update(t);
@@ -18,8 +25,8 @@ let s = class extends d {
18
25
  this.registerTheme(this.theme);
19
26
  }
20
27
  registerTheme(t) {
21
- const e = getComputedStyle(this).getPropertyValue("--re-text-color").trim(), r = getComputedStyle(this).getPropertyValue("--re-tile-background-color").trim();
22
- this.themeBgColor = r || this.theme?.theme_object?.backgroundColor, this.themeTitleColor = e || this.theme?.theme_object?.title?.textStyle?.color;
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;
23
30
  }
24
31
  handleNavItemClick(t) {
25
32
  const e = new CustomEvent("nav-submit", {
@@ -38,10 +45,10 @@ let s = class extends d {
38
45
  for (const r of t.variables)
39
46
  r.label && (e = e.split(`{{${r.label}}}`).join(encodeURIComponent(String(r.value ?? ""))));
40
47
  if (e.includes("*")) {
41
- const r = (this.route || "").split("/").filter(Boolean), o = e.split("/").filter(Boolean);
42
- for (let i = 0; i < o.length; i++)
43
- o[i] === "*" && (o[i] = r[i] ?? "");
44
- e = (e.startsWith("/") ? "/" : "") + o.filter(Boolean).join("/");
48
+ const r = (this.route || "").split("/").filter(Boolean), i = e.split("/").filter(Boolean);
49
+ for (let o = 0; o < i.length; o++)
50
+ i[o] === "*" && (i[o] = r[o] ?? "");
51
+ e = (e.startsWith("/") ? "/" : "") + i.filter(Boolean).join("/");
45
52
  }
46
53
  return e;
47
54
  }
@@ -52,12 +59,12 @@ let s = class extends d {
52
59
  return t.startsWith("/") ? e.startsWith(r) : e.endsWith(r) || e === r;
53
60
  }
54
61
  render() {
55
- const t = this.inputData?.style?.fontSize ?? 16, e = (this.inputData?.style?.fontSize ?? 16) * 1.5, r = 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", a = t * 0.4;
56
63
  return c`
57
64
  <div
58
65
  class="wrapper"
59
- style="background-color: ${this.inputData?.style?.backgroundColor || this.themeBgColor}; color: ${this.inputData?.style?.color || this.themeTitleColor};
60
- font-weight: ${this.inputData?.style?.fontWeight};
66
+ style="background-color: ${o}; color: ${i};
67
+ font-weight: ${e};
61
68
  font-size: ${t}px;"
62
69
  >
63
70
  <h2
@@ -74,22 +81,21 @@ let s = class extends d {
74
81
  ${this.inputData?.title}
75
82
  </h2>
76
83
  <div class="nav-list">
77
- ${b(
84
+ ${m(
78
85
  this.inputData?.navItems || [],
79
- (o) => o.label,
80
- (o) => c`
86
+ (s) => s.label,
87
+ (s) => c`
81
88
  <div
82
- class="nav-item ${this.matchesRoute(this.resolveRoute(o)) ? "selected" : ""}"
83
- style="gap: ${r}px;"
84
- @click=${() => this.handleNavItemClick(this.resolveRoute(o))}
89
+ class="nav-item ${this.matchesRoute(this.resolveRoute(s)) ? "selected" : ""}"
90
+ style="gap: ${a}px;"
91
+ @click=${() => this.handleNavItemClick(this.resolveRoute(s))}
85
92
  >
86
- ${o.iconName ? c`
87
- <md-icon
88
- style="font-size: ${e}px;width: ${e}px;"
89
- >${o.iconName}
93
+ ${s.iconName ? c`
94
+ <md-icon style="--md-icon-size: ${r}px;"
95
+ >${s.iconName}
90
96
  </md-icon>
91
97
  ` : ""}
92
- ${o.label}
98
+ ${s.label}
93
99
  </div>
94
100
  `
95
101
  )}
@@ -98,7 +104,7 @@ let s = class extends d {
98
104
  `;
99
105
  }
100
106
  };
101
- s.styles = u`
107
+ n.styles = u`
102
108
  :host {
103
109
  display: block;
104
110
  font-family: sans-serif;
@@ -164,35 +170,40 @@ s.styles = u`
164
170
  font-family: 'Material Symbols Outlined';
165
171
  }
166
172
 
173
+ /* Derive the highlight from the (inherited) text color, like the
174
+ scrollbar above — a fixed black wash is invisible on a dark nav. */
167
175
  .selected {
168
- background-color: rgba(0, 0, 0, 0.1);
176
+ background-color: color-mix(in srgb, currentColor 15%, transparent);
169
177
  }
170
178
 
171
179
  h2 {
172
180
  margin: 0;
173
181
  padding: 0px;
174
182
  font-size: 1.2em;
183
+ /* the UA stylesheet forces bold, which would ignore the
184
+ configured font weight */
185
+ font-weight: inherit;
175
186
  }
176
187
  `;
177
188
  l([
178
- p({ type: Object })
179
- ], s.prototype, "inputData", 2);
189
+ h({ type: Object })
190
+ ], n.prototype, "inputData", 2);
180
191
  l([
181
- p({ type: Object })
182
- ], s.prototype, "theme", 2);
192
+ h({ type: Object })
193
+ ], n.prototype, "theme", 2);
183
194
  l([
184
- p({ type: String })
185
- ], s.prototype, "route", 2);
195
+ h({ type: String })
196
+ ], n.prototype, "route", 2);
186
197
  l([
187
- h()
188
- ], s.prototype, "themeBgColor", 2);
198
+ p()
199
+ ], n.prototype, "themeBgColor", 2);
189
200
  l([
190
- h()
191
- ], s.prototype, "themeTitleColor", 2);
192
- s = l([
193
- m("widget-sidenav-1.0.16")
194
- ], s);
201
+ p()
202
+ ], n.prototype, "themeTitleColor", 2);
203
+ n = l([
204
+ g("widget-sidenav-1.0.17")
205
+ ], n);
195
206
  export {
196
- s as WidgetSidenav
207
+ n as WidgetSidenav
197
208
  };
198
209
  //# sourceMappingURL=widget-sidenav.js.map
@@ -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@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 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: 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 .selected {\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 }\n `\n\n render() {\n const fontSize = this.inputData?.style?.fontSize ?? 16\n const iconFontSize = (this.inputData?.style?.fontSize ?? 16) * 1.5\n const gap = fontSize * 0.4\n return html`\n <div\n class=\"wrapper\"\n style=\"background-color: ${this.inputData?.style?.backgroundColor ||\n this.themeBgColor}; color: ${this.inputData?.style?.color || this.themeTitleColor};\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 <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\n style=\"font-size: ${iconFontSize}px;width: ${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":["WidgetSidenav","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","route","event","item","variable","currentSegments","routeSegments","itemRoute","subRoute","fontSize","iconFontSize","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 { 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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"}
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.16",
6
+ "version": "1.0.17",
7
7
  "engines": {
8
8
  "node": ">=24.9.0",
9
9
  "npm": ">=10.0.2"
@@ -9,6 +9,26 @@ type Theme = {
9
9
  theme_name: string
10
10
  theme_object: any
11
11
  }
12
+
13
+ /**
14
+ * ECharts themes describe a *chart canvas*, and most of them set
15
+ * `backgroundColor` to a fully transparent colour (the light theme uses
16
+ * `rgba(0, 0, 0, 0)`). That is a valid, truthy colour string, so using it
17
+ * verbatim as the nav background paints nothing at all. Treat any
18
+ * fully transparent theme colour as "no colour" so the fallback kicks in.
19
+ */
20
+ const isTransparent = (color?: string) => {
21
+ if (!color) return true
22
+ const value = color.trim().toLowerCase()
23
+ if (value === 'transparent') return true
24
+ const functional = value.match(/^(?:rgba|hsla)\([^)]*[,/]\s*([\d.]+%?)\s*\)$/)
25
+ if (functional) return parseFloat(functional[1]) === 0
26
+ // #rrggbbaa / #rgba
27
+ if (/^#[0-9a-f]{8}$/.test(value)) return value.slice(7) === '00'
28
+ if (/^#[0-9a-f]{4}$/.test(value)) return value[4] === '0'
29
+ return false
30
+ }
31
+
12
32
  @customElement('widget-sidenav-versionplaceholder')
13
33
  export class WidgetSidenav extends LitElement {
14
34
  @property({ type: Object }) inputData?: InputData
@@ -35,8 +55,9 @@ export class WidgetSidenav extends LitElement {
35
55
  registerTheme(theme?: Theme) {
36
56
  const cssTextColor = getComputedStyle(this).getPropertyValue('--re-text-color').trim()
37
57
  const cssBgColor = getComputedStyle(this).getPropertyValue('--re-tile-background-color').trim()
38
- this.themeBgColor = cssBgColor || this.theme?.theme_object?.backgroundColor
39
- this.themeTitleColor = cssTextColor || this.theme?.theme_object?.title?.textStyle?.color
58
+ const themeBgColor = theme?.theme_object?.backgroundColor
59
+ this.themeBgColor = cssBgColor || (isTransparent(themeBgColor) ? undefined : themeBgColor)
60
+ this.themeTitleColor = cssTextColor || theme?.theme_object?.title?.textStyle?.color
40
61
  }
41
62
 
42
63
  handleNavItemClick(route?: string) {
@@ -157,27 +178,34 @@ export class WidgetSidenav extends LitElement {
157
178
  font-family: 'Material Symbols Outlined';
158
179
  }
159
180
 
181
+ /* Derive the highlight from the (inherited) text color, like the
182
+ scrollbar above — a fixed black wash is invisible on a dark nav. */
160
183
  .selected {
161
- background-color: rgba(0, 0, 0, 0.1);
184
+ background-color: color-mix(in srgb, currentColor 15%, transparent);
162
185
  }
163
186
 
164
187
  h2 {
165
188
  margin: 0;
166
189
  padding: 0px;
167
190
  font-size: 1.2em;
191
+ /* the UA stylesheet forces bold, which would ignore the
192
+ configured font weight */
193
+ font-weight: inherit;
168
194
  }
169
195
  `
170
196
 
171
197
  render() {
172
198
  const fontSize = this.inputData?.style?.fontSize ?? 16
173
- const iconFontSize = (this.inputData?.style?.fontSize ?? 16) * 1.5
199
+ const fontWeight = this.inputData?.style?.fontWeight ?? 400
200
+ const iconFontSize = fontSize * 1.5
201
+ const fontColor = this.inputData?.style?.color || this.themeTitleColor || 'black'
202
+ const bgColor = this.inputData?.style?.backgroundColor || this.themeBgColor || 'white'
174
203
  const gap = fontSize * 0.4
175
204
  return html`
176
205
  <div
177
206
  class="wrapper"
178
- style="background-color: ${this.inputData?.style?.backgroundColor ||
179
- this.themeBgColor}; color: ${this.inputData?.style?.color || this.themeTitleColor};
180
- font-weight: ${this.inputData?.style?.fontWeight};
207
+ style="background-color: ${bgColor}; color: ${fontColor};
208
+ font-weight: ${fontWeight};
181
209
  font-size: ${fontSize}px;"
182
210
  >
183
211
  <h2
@@ -208,8 +236,7 @@ export class WidgetSidenav extends LitElement {
208
236
  >
209
237
  ${item.iconName
210
238
  ? html`
211
- <md-icon
212
- style="font-size: ${iconFontSize}px;width: ${iconFontSize}px;"
239
+ <md-icon style="--md-icon-size: ${iconFontSize}px;"
213
240
  >${item.iconName}
214
241
  </md-icon>
215
242
  `