@record-evolution/widget-navbutton 1.0.7 → 1.0.8
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-navbutton.js +48 -35
- package/dist/widget-navbutton.js.map +1 -1
- package/package.json +1 -1
- package/src/definition-schema.d.ts +14 -7
- package/src/definition-schema.json +23 -13
- package/src/widget-navbutton.ts +27 -10
package/dist/widget-navbutton.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { css as c, LitElement as
|
|
2
|
-
import { property as
|
|
1
|
+
import { css as c, LitElement as h, html as u } from "lit";
|
|
2
|
+
import { property as p, state as m, customElement as d } from "lit/decorators.js";
|
|
3
3
|
import "@material/web/icon/icon.js";
|
|
4
4
|
import "@material/web/button/filled-button.js";
|
|
5
5
|
import "@material/web/ripple/ripple.js";
|
|
6
|
-
var f = Object.defineProperty, b = Object.getOwnPropertyDescriptor, s = (t, e, o,
|
|
7
|
-
for (var i =
|
|
8
|
-
(a = t[n]) && (i = (
|
|
9
|
-
return
|
|
6
|
+
var f = Object.defineProperty, b = Object.getOwnPropertyDescriptor, s = (t, e, o, r) => {
|
|
7
|
+
for (var i = r > 1 ? void 0 : r ? b(e, o) : e, n = t.length - 1, a; n >= 0; n--)
|
|
8
|
+
(a = t[n]) && (i = (r ? a(e, o, i) : a(i)) || i);
|
|
9
|
+
return r && i && f(e, o, i), i;
|
|
10
10
|
};
|
|
11
|
-
let
|
|
11
|
+
let l = class extends h {
|
|
12
12
|
constructor() {
|
|
13
|
-
super(...arguments), this.version = "1.0.
|
|
13
|
+
super(...arguments), this.version = "1.0.8";
|
|
14
14
|
}
|
|
15
15
|
update(t) {
|
|
16
16
|
t.has("theme") && this.registerTheme(this.theme), super.update(t);
|
|
@@ -22,31 +22,44 @@ let r = class extends d {
|
|
|
22
22
|
const e = getComputedStyle(this).getPropertyValue("--re-text-color").trim(), o = getComputedStyle(this).getPropertyValue("--re-tile-background-color").trim();
|
|
23
23
|
this.themeBgColor = o || this.theme?.theme_object?.backgroundColor, this.themeTitleColor = e || this.theme?.theme_object?.title?.textStyle?.color;
|
|
24
24
|
}
|
|
25
|
-
handleNavItemClick(
|
|
26
|
-
let
|
|
27
|
-
this.inputData?.route === "" ? (
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
handleNavItemClick() {
|
|
26
|
+
let t;
|
|
27
|
+
this.inputData?.route === "" ? (t = "/" + this.route?.split("/").filter(Boolean).slice(0, -1).join("/") + "/" || "/", t = t === "//" ? "/" : t) : t = this.resolveRoute({
|
|
28
|
+
route: this.inputData?.route,
|
|
29
|
+
variables: this.inputData?.variables
|
|
30
|
+
}) || "/";
|
|
31
|
+
const e = new CustomEvent("nav-submit", {
|
|
32
|
+
detail: { path: t },
|
|
30
33
|
bubbles: !0,
|
|
31
34
|
composed: !0
|
|
32
35
|
});
|
|
33
|
-
this.dispatchEvent(
|
|
36
|
+
this.dispatchEvent(e);
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
resolveRoute(t) {
|
|
39
|
+
let e = String(t?.route ?? "");
|
|
40
|
+
if (t?.variables)
|
|
41
|
+
for (const o of t.variables)
|
|
42
|
+
o.label && (e = e.split(`{{${o.label}}}`).join(encodeURIComponent(String(o.value ?? ""))));
|
|
43
|
+
if (e.includes("*")) {
|
|
44
|
+
const o = (this.route || "").split("/").filter(Boolean), r = e.split("/").filter(Boolean);
|
|
45
|
+
for (let i = 0; i < r.length; i++)
|
|
46
|
+
r[i] === "*" && (r[i] = o[i] ?? "");
|
|
47
|
+
e = (e.startsWith("/") ? "/" : "") + r.filter(Boolean).join("/");
|
|
48
|
+
}
|
|
49
|
+
return e;
|
|
37
50
|
}
|
|
38
51
|
render() {
|
|
39
|
-
const t = this.inputData?.style?.fontSize ?? 16, e = (this.inputData?.style?.fontSize ?? 16) * 1.5, o = this.inputData?.style?.color || this.themeTitleColor || "black",
|
|
40
|
-
return
|
|
52
|
+
const t = this.inputData?.style?.fontSize ?? 16, e = (this.inputData?.style?.fontSize ?? 16) * 1.5, o = this.inputData?.style?.color || this.themeTitleColor || "black", r = this.inputData?.style?.backgroundColor || this.themeBgColor || "white";
|
|
53
|
+
return u`
|
|
41
54
|
<md-filled-button
|
|
42
55
|
style="font-size: ${t}px;
|
|
43
56
|
--md-filled-button-label-text-color: ${o};
|
|
44
57
|
--md-filled-button-hover-label-text-color: ${o};
|
|
45
58
|
--md-filled-button-pressed-label-text-color: ${o};
|
|
46
59
|
--md-filled-button-focus-label-text-color: ${o};
|
|
47
|
-
--md-filled-button-container-color: ${
|
|
60
|
+
--md-filled-button-container-color: ${r};
|
|
48
61
|
"
|
|
49
|
-
@click=${() => this.handleNavItemClick(
|
|
62
|
+
@click=${() => this.handleNavItemClick()}
|
|
50
63
|
>
|
|
51
64
|
${this.inputData?.title}
|
|
52
65
|
<md-ripple></md-ripple>
|
|
@@ -57,7 +70,7 @@ let r = class extends d {
|
|
|
57
70
|
`;
|
|
58
71
|
}
|
|
59
72
|
};
|
|
60
|
-
|
|
73
|
+
l.styles = c`
|
|
61
74
|
:host {
|
|
62
75
|
display: flex;
|
|
63
76
|
align-items: center;
|
|
@@ -83,24 +96,24 @@ r.styles = c`
|
|
|
83
96
|
}
|
|
84
97
|
`;
|
|
85
98
|
s([
|
|
86
|
-
|
|
87
|
-
],
|
|
99
|
+
p({ type: Object })
|
|
100
|
+
], l.prototype, "inputData", 2);
|
|
88
101
|
s([
|
|
89
|
-
|
|
90
|
-
],
|
|
102
|
+
p({ type: Object })
|
|
103
|
+
], l.prototype, "theme", 2);
|
|
91
104
|
s([
|
|
92
|
-
|
|
93
|
-
],
|
|
105
|
+
p({ type: String })
|
|
106
|
+
], l.prototype, "route", 2);
|
|
94
107
|
s([
|
|
95
|
-
|
|
96
|
-
],
|
|
108
|
+
m()
|
|
109
|
+
], l.prototype, "themeBgColor", 2);
|
|
97
110
|
s([
|
|
98
|
-
|
|
99
|
-
],
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
],
|
|
111
|
+
m()
|
|
112
|
+
], l.prototype, "themeTitleColor", 2);
|
|
113
|
+
l = s([
|
|
114
|
+
d("widget-navbutton-1.0.8")
|
|
115
|
+
], l);
|
|
103
116
|
export {
|
|
104
|
-
|
|
117
|
+
l as WidgetNavbutton
|
|
105
118
|
};
|
|
106
119
|
//# sourceMappingURL=widget-navbutton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget-navbutton.js","sources":["../src/widget-navbutton.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { InputData } from './definition-schema'\n\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/filled-button.js'\nimport '@material/web/ripple/ripple.js'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\n\n@customElement('widget-navbutton-versionplaceholder')\nexport class WidgetNavbutton 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(
|
|
1
|
+
{"version":3,"file":"widget-navbutton.js","sources":["../src/widget-navbutton.ts"],"sourcesContent":["import { html, css, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { InputData } from './definition-schema'\n\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/filled-button.js'\nimport '@material/web/ripple/ripple.js'\n\ntype Theme = {\n theme_name: string\n theme_object: any\n}\n\n@customElement('widget-navbutton-versionplaceholder')\nexport class WidgetNavbutton 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() {\n let goto: string\n if (this.inputData?.route === '') {\n goto = '/' + this.route?.split('/').filter(Boolean).slice(0, -1).join('/') + '/' || '/'\n goto = goto === '//' ? '/' : goto\n } else {\n goto =\n this.resolveRoute({\n route: this.inputData?.route,\n variables: this.inputData?.variables\n }) || '/'\n }\n const event = new CustomEvent('nav-submit', {\n detail: { path: goto },\n bubbles: true,\n composed: true\n })\n this.dispatchEvent(event)\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 static styles = css`\n :host {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n font-family: sans-serif;\n box-sizing: border-box;\n margin: auto;\n padding: 2cqh 2cqw;\n }\n\n md-icon {\n font-family: 'Material Symbols Outlined';\n }\n md-filled-button {\n flex: 1;\n --md-filled-button-container-shape: 4px;\n --md-filled-button-container-shadow-color: none;\n --md-sys-color-primary: #006a6a;\n --md-ripple-hover-color: var(--md-sys-color-primary);\n --md-ripple-pressed-color: var(--md-sys-color-primary);\n }\n `\n\n render() {\n const fontSize = this.inputData?.style?.fontSize ?? 16\n const iconFontSize = (this.inputData?.style?.fontSize ?? 16) * 1.5\n const fontColor = this.inputData?.style?.color || this.themeTitleColor || 'black'\n const bgColor = this.inputData?.style?.backgroundColor || this.themeBgColor || 'white'\n const gap = fontSize * 0.4\n return html`\n <md-filled-button\n style=\"font-size: ${fontSize}px; \n --md-filled-button-label-text-color: ${fontColor}; \n --md-filled-button-hover-label-text-color: ${fontColor};\n --md-filled-button-pressed-label-text-color: ${fontColor};\n --md-filled-button-focus-label-text-color: ${fontColor};\n --md-filled-button-container-color: ${bgColor};\n \"\n @click=${() => this.handleNavItemClick()}\n >\n ${this.inputData?.title}\n <md-ripple></md-ripple>\n <md-icon slot=\"icon\" style=\"font-size: ${iconFontSize}px; color: ${fontColor}\"\n >${this.inputData?.iconName}</md-icon\n >\n </md-filled-button>\n `\n }\n}\n"],"names":["WidgetNavbutton","LitElement","changedProperties","_changedProperties","theme","cssTextColor","cssBgColor","goto","event","item","route","variable","currentSegments","routeSegments","fontSize","iconFontSize","fontColor","bgColor","html","css","__decorateClass","property","state","customElement"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -14,17 +14,25 @@ export type Label = string;
|
|
|
14
14
|
*/
|
|
15
15
|
export type IconName = string;
|
|
16
16
|
/**
|
|
17
|
-
* The destination path when the button is clicked. Leave blank to perform automatic browser back navigation.
|
|
17
|
+
* The destination path when the button is clicked. Leave blank to perform automatic browser back navigation. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/* /settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.
|
|
18
18
|
*/
|
|
19
19
|
export type Navigation = string;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.
|
|
22
22
|
*/
|
|
23
|
-
export type
|
|
23
|
+
export type Label1 = string;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.
|
|
26
26
|
*/
|
|
27
|
-
export type
|
|
27
|
+
export type Value = string;
|
|
28
|
+
/**
|
|
29
|
+
* Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.
|
|
30
|
+
*/
|
|
31
|
+
export type NavigationVariables = {
|
|
32
|
+
label?: Label1;
|
|
33
|
+
value?: Value;
|
|
34
|
+
[k: string]: unknown;
|
|
35
|
+
}[];
|
|
28
36
|
/**
|
|
29
37
|
* Font size in pixels for the button label text.
|
|
30
38
|
*/
|
|
@@ -37,8 +45,7 @@ export interface InputData {
|
|
|
37
45
|
title?: Label;
|
|
38
46
|
iconName?: IconName;
|
|
39
47
|
route?: Navigation;
|
|
40
|
-
|
|
41
|
-
trailingSlash?: AddTraillingSlash;
|
|
48
|
+
variables?: NavigationVariables;
|
|
42
49
|
style?: ButtonStyle;
|
|
43
50
|
[k: string]: unknown;
|
|
44
51
|
}
|
|
@@ -19,22 +19,32 @@
|
|
|
19
19
|
"route": {
|
|
20
20
|
"title": "Navigation",
|
|
21
21
|
"order": 3,
|
|
22
|
-
"description": "The destination path when the button is clicked. Leave blank to perform automatic browser back navigation.
|
|
22
|
+
"description": "The destination path when the button is clicked. Leave blank to perform automatic browser back navigation. Supports two dynamic substitution mechanisms: (1) Variable placeholders using double curly braces — define variables in the 'Variables' array below and reference them as {{variableName}} in the route string (e.g., '/device/{{deviceId}}/details' where a variable with label 'deviceId' provides the value). (2) Wildcard segments using a single asterisk '*' as a full path segment — each '*' is replaced at runtime by the segment at the same position from the current browser route (e.g., '/*/settings' navigates to the settings page while preserving the first segment of the current URL). The '*' must be the entire segment to be substituted; partial wildcards like 'test*' are treated as literal text. Routes starting with '/' are absolute; routes without a leading slash are relative to the current location.",
|
|
23
23
|
"type": "string"
|
|
24
24
|
},
|
|
25
|
-
"
|
|
26
|
-
"title": "
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"dataDrivenDisabled": true,
|
|
30
|
-
"type": "boolean"
|
|
31
|
-
},
|
|
32
|
-
"trailingSlash": {
|
|
33
|
-
"title": "Add Trailling Slash",
|
|
34
|
-
"order": 5,
|
|
35
|
-
"description": "When enabled, appends '/' to the end of the navigation route. Required by some routing configurations for proper page matching.",
|
|
25
|
+
"variables": {
|
|
26
|
+
"title": "Navigation Variables",
|
|
27
|
+
"description": "Array of variable definitions for dynamic route segment substitution. Each variable has a label (used in the route string as {{label}}) and a value (the replacement text). Values can be static or bound to data columns for real-time updates.",
|
|
28
|
+
"type": "array",
|
|
36
29
|
"dataDrivenDisabled": true,
|
|
37
|
-
"
|
|
30
|
+
"order": 4,
|
|
31
|
+
"items": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"properties": {
|
|
34
|
+
"label": {
|
|
35
|
+
"title": "Label",
|
|
36
|
+
"description": "The variable name used in the route string. Reference this in your route using the {{label}} syntax. Use descriptive names like 'temperature', 'status', 'deviceName'.",
|
|
37
|
+
"type": "string",
|
|
38
|
+
"order": 1
|
|
39
|
+
},
|
|
40
|
+
"value": {
|
|
41
|
+
"title": "Value",
|
|
42
|
+
"description": "The replacement text that will appear in place of {{label}} in the rendered output. Can be a static value or bound to a data column for dynamic updates.",
|
|
43
|
+
"type": "string",
|
|
44
|
+
"order": 2
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
38
48
|
},
|
|
39
49
|
"style": {
|
|
40
50
|
"title": "Button Style",
|
package/src/widget-navbutton.ts
CHANGED
|
@@ -41,15 +41,18 @@ export class WidgetNavbutton extends LitElement {
|
|
|
41
41
|
this.themeTitleColor = cssTextColor || this.theme?.theme_object?.title?.textStyle?.color
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
handleNavItemClick(
|
|
44
|
+
handleNavItemClick() {
|
|
45
45
|
let goto: string
|
|
46
46
|
if (this.inputData?.route === '') {
|
|
47
47
|
goto = '/' + this.route?.split('/').filter(Boolean).slice(0, -1).join('/') + '/' || '/'
|
|
48
48
|
goto = goto === '//' ? '/' : goto
|
|
49
49
|
} else {
|
|
50
|
-
goto =
|
|
50
|
+
goto =
|
|
51
|
+
this.resolveRoute({
|
|
52
|
+
route: this.inputData?.route,
|
|
53
|
+
variables: this.inputData?.variables
|
|
54
|
+
}) || '/'
|
|
51
55
|
}
|
|
52
|
-
console.log('Navigating to:', route, this.route, { goto })
|
|
53
56
|
const event = new CustomEvent('nav-submit', {
|
|
54
57
|
detail: { path: goto },
|
|
55
58
|
bubbles: true,
|
|
@@ -58,14 +61,28 @@ export class WidgetNavbutton extends LitElement {
|
|
|
58
61
|
this.dispatchEvent(event)
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
resolveRoute(item?: any): string | undefined {
|
|
65
|
+
let route = String(item?.route ?? '')
|
|
66
|
+
if (item?.variables) {
|
|
67
|
+
for (const variable of item.variables) {
|
|
68
|
+
if (variable.label) {
|
|
69
|
+
route = route
|
|
70
|
+
.split(`{{${variable.label}}}`)
|
|
71
|
+
.join(encodeURIComponent(String(variable.value ?? '')))
|
|
72
|
+
}
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
75
|
+
if (route.includes('*')) {
|
|
76
|
+
const currentSegments = (this.route || '').split('/').filter(Boolean)
|
|
77
|
+
const routeSegments = route.split('/').filter(Boolean)
|
|
78
|
+
for (let i = 0; i < routeSegments.length; i++) {
|
|
79
|
+
if (routeSegments[i] === '*') {
|
|
80
|
+
routeSegments[i] = currentSegments[i] ?? ''
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
route = (route.startsWith('/') ? '/' : '') + routeSegments.filter(Boolean).join('/')
|
|
67
84
|
}
|
|
68
|
-
return
|
|
85
|
+
return route
|
|
69
86
|
}
|
|
70
87
|
|
|
71
88
|
static styles = css`
|
|
@@ -109,7 +126,7 @@ export class WidgetNavbutton extends LitElement {
|
|
|
109
126
|
--md-filled-button-focus-label-text-color: ${fontColor};
|
|
110
127
|
--md-filled-button-container-color: ${bgColor};
|
|
111
128
|
"
|
|
112
|
-
@click=${() => this.handleNavItemClick(
|
|
129
|
+
@click=${() => this.handleNavItemClick()}
|
|
113
130
|
>
|
|
114
131
|
${this.inputData?.title}
|
|
115
132
|
<md-ripple></md-ripple>
|