@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.
- package/dist/widget-sidenav.js +55 -44
- package/dist/widget-sidenav.js.map +1 -1
- package/package.json +1 -1
- package/src/widget-sidenav.ts +36 -9
package/dist/widget-sidenav.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { css as u, LitElement as d, html as c } from "lit";
|
|
2
|
-
import { property as
|
|
3
|
-
import { repeat as
|
|
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
|
|
6
|
-
for (var
|
|
7
|
-
(
|
|
8
|
-
return
|
|
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
|
-
|
|
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.
|
|
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 ||
|
|
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),
|
|
42
|
-
for (let
|
|
43
|
-
o
|
|
44
|
-
e = (e.startsWith("/") ? "/" : "") +
|
|
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 =
|
|
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: ${
|
|
60
|
-
font-weight: ${
|
|
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
|
-
${
|
|
84
|
+
${m(
|
|
78
85
|
this.inputData?.navItems || [],
|
|
79
|
-
(
|
|
80
|
-
(
|
|
86
|
+
(s) => s.label,
|
|
87
|
+
(s) => c`
|
|
81
88
|
<div
|
|
82
|
-
class="nav-item ${this.matchesRoute(this.resolveRoute(
|
|
83
|
-
style="gap: ${
|
|
84
|
-
@click=${() => this.handleNavItemClick(this.resolveRoute(
|
|
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
|
-
${
|
|
87
|
-
<md-icon
|
|
88
|
-
|
|
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
|
-
${
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
179
|
-
],
|
|
189
|
+
h({ type: Object })
|
|
190
|
+
], n.prototype, "inputData", 2);
|
|
180
191
|
l([
|
|
181
|
-
|
|
182
|
-
],
|
|
192
|
+
h({ type: Object })
|
|
193
|
+
], n.prototype, "theme", 2);
|
|
183
194
|
l([
|
|
184
|
-
|
|
185
|
-
],
|
|
195
|
+
h({ type: String })
|
|
196
|
+
], n.prototype, "route", 2);
|
|
186
197
|
l([
|
|
187
|
-
|
|
188
|
-
],
|
|
198
|
+
p()
|
|
199
|
+
], n.prototype, "themeBgColor", 2);
|
|
189
200
|
l([
|
|
190
|
-
|
|
191
|
-
],
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
],
|
|
201
|
+
p()
|
|
202
|
+
], n.prototype, "themeTitleColor", 2);
|
|
203
|
+
n = l([
|
|
204
|
+
g("widget-sidenav-1.0.17")
|
|
205
|
+
], n);
|
|
195
206
|
export {
|
|
196
|
-
|
|
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
package/src/widget-sidenav.ts
CHANGED
|
@@ -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
|
-
|
|
39
|
-
this.
|
|
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:
|
|
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
|
|
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: ${
|
|
179
|
-
|
|
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
|
`
|