@schukai/monster 4.10.4 → 4.11.1

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.
@@ -10,10 +10,10 @@
10
10
  * For more information about purchasing a commercial license, please contact schukai GmbH.
11
11
  */
12
12
 
13
- import {addAttributeToken} from "../../../dom/attributes.mjs";
14
- import {ATTRIBUTE_ERRORMESSAGE} from "../../../dom/constants.mjs";
13
+ import { addAttributeToken } from "../../../dom/attributes.mjs";
14
+ import { ATTRIBUTE_ERRORMESSAGE } from "../../../dom/constants.mjs";
15
15
 
16
- export {CameraCaptureStyleSheet}
16
+ export { CameraCaptureStyleSheet };
17
17
 
18
18
  /**
19
19
  * @private
@@ -22,10 +22,17 @@ export {CameraCaptureStyleSheet}
22
22
  const CameraCaptureStyleSheet = new CSSStyleSheet();
23
23
 
24
24
  try {
25
- CameraCaptureStyleSheet.insertRule(`
25
+ CameraCaptureStyleSheet.insertRule(
26
+ `
26
27
  @layer cameracapture {
27
28
  [data-monster-role=control]{box-sizing:border-box;outline:none;width:100%}[data-monster-role=control].flex{align-items:center;display:flex;flex-direction:row}:host{box-sizing:border-box;display:block}:after,:before,:root{--monster-font-family:-apple-system,BlinkMacSystemFont,\"Quicksand\",\"Segoe UI\",\"Roboto\",\"Oxygen\",\"Ubuntu\",\"Cantarell\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\";--monster-font-family-monospace:\"Consolas\",\"Courier New\",\"Roboto Mono\",\"Source Code Pro\",\"Fira Mono\",monospace;--monster-color-primary-1:var(--monster-color-gray-6);--monster-color-primary-2:var(--monster-color-gray-6);--monster-color-primary-3:var(--monster-color-cinnamon-1);--monster-color-primary-4:var(--monster-color-cinnamon-1);--monster-bg-color-primary-1:var(--monster-color-gray-1);--monster-bg-color-primary-2:var(--monster-color-gray-2);--monster-bg-color-primary-3:var(--monster-color-gray-6);--monster-bg-color-primary-4:var(--monster-color-gray-4)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-1:var(--monster-color-gray-1);--monster-color-primary-2:var(--monster-color-gray-1);--monster-color-primary-3:var(--monster-color-gray-6);--monster-color-primary-4:var(--monster-color-gray-6);--monster-bg-color-primary-1:var(--monster-color-gray-6);--monster-bg-color-primary-2:var(--monster-color-gray-3);--monster-bg-color-primary-3:var(--monster-color-gray-2);--monster-bg-color-primary-4:var(--monster-color-gray-1)}}:after,:before,:root{--monster-color-secondary-1:var(--monster-color-red-4);--monster-color-secondary-2:var(--monster-color-red-4);--monster-color-secondary-3:var(--monster-color-red-1);--monster-color-secondary-4:var(--monster-color-red-1);--monster-bg-color-secondary-1:var(--monster-color-gray-1);--monster-bg-color-secondary-2:var(--monster-color-red-2);--monster-bg-color-secondary-3:var(--monster-color-red-3);--monster-bg-color-secondary-4:var(--monster-color-red-6)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-secondary-1:var(--monster-color-red-1);--monster-color-secondary-2:var(--monster-color-red-1);--monster-color-secondary-3:var(--monster-color-red-6);--monster-color-secondary-4:var(--monster-color-red-4);--monster-bg-color-secondary-1:var(--monster-color-gray-6);--monster-bg-color-secondary-2:var(--monster-color-red-3);--monster-bg-color-secondary-3:var(--monster-color-red-2);--monster-bg-color-secondary-4:var(--monster-color-red-1)}}:after,:before,:root{--monster-color-tertiary-1:var(--monster-color-magenta-4);--monster-color-tertiary-2:var(--monster-color-magenta-4);--monster-color-tertiary-3:var(--monster-color-magenta-6);--monster-color-tertiary-4:var(--monster-color-magenta-1);--monster-bg-color-tertiary-1:var(--monster-color-gray-1);--monster-bg-color-tertiary-2:var(--monster-color-magenta-1);--monster-bg-color-tertiary-3:var(--monster-color-magenta-2);--monster-bg-color-tertiary-4:var(--monster-color-magenta-6)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-tertiary-1:var(--monster-color-magenta-1);--monster-color-tertiary-2:var(--monster-color-magenta-6);--monster-color-tertiary-3:var(--monster-color-magenta-4);--monster-color-tertiary-4:var(--monster-color-magenta-4);--monster-bg-color-tertiary-1:var(--monster-color-gray-6);--monster-bg-color-tertiary-2:var(--monster-color-magenta-2);--monster-bg-color-tertiary-3:var(--monster-color-magenta-1);--monster-bg-color-tertiary-4:var(--monster-color-magenta-1)}}:after,:before,:root{--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-4);--monster-color-destructive-3:var(--monster-color-red-6);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-4);--monster-bg-color-destructive-2:var(--monster-color-gray-1);--monster-bg-color-destructive-3:var(--monster-color-red-2);--monster-bg-color-destructive-4:var(--monster-color-red-5)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-destructive-1:var(--monster-color-red-1);--monster-color-destructive-2:var(--monster-color-red-3);--monster-color-destructive-3:var(--monster-color-red-4);--monster-color-destructive-4:var(--monster-color-red-1);--monster-bg-color-destructive-1:var(--monster-color-red-5);--monster-bg-color-destructive-2:var(--monster-color-gray-6);--monster-bg-color-destructive-3:var(--monster-color-red-1);--monster-bg-color-destructive-4:var(--monster-color-red-4)}}:after,:before,:root{--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-4);--monster-color-success-3:var(--monster-color-green-6);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-3);--monster-bg-color-success-2:var(--monster-color-gray-1);--monster-bg-color-success-3:var(--monster-color-green-2);--monster-bg-color-success-4:var(--monster-color-green-5)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-success-1:var(--monster-color-green-1);--monster-color-success-2:var(--monster-color-green-2);--monster-color-success-3:var(--monster-color-green-4);--monster-color-success-4:var(--monster-color-green-1);--monster-bg-color-success-1:var(--monster-color-green-5);--monster-bg-color-success-2:var(--monster-color-gray-6);--monster-bg-color-success-3:var(--monster-color-green-1);--monster-bg-color-success-4:var(--monster-color-green-3)}}:after,:before,:root{--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-4);--monster-color-warning-3:var(--monster-color-orange-6);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-3);--monster-bg-color-warning-2:var(--monster-color-gray-1);--monster-bg-color-warning-3:var(--monster-color-orange-2);--monster-bg-color-warning-4:var(--monster-color-orange-5)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-warning-1:var(--monster-color-orange-1);--monster-color-warning-2:var(--monster-color-orange-3);--monster-color-warning-3:var(--monster-color-orange-4);--monster-color-warning-4:var(--monster-color-orange-1);--monster-bg-color-warning-1:var(--monster-color-orange-5);--monster-bg-color-warning-2:var(--monster-color-gray-6);--monster-bg-color-warning-3:var(--monster-color-orange-1);--monster-bg-color-warning-4:var(--monster-color-orange-3)}}:after,:before,:root{--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-4);--monster-color-error-3:var(--monster-color-red-6);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-4);--monster-bg-color-error-2:var(--monster-color-gray-1);--monster-bg-color-error-3:var(--monster-color-red-2);--monster-bg-color-error-4:var(--monster-color-red-5)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-error-1:var(--monster-color-red-1);--monster-color-error-2:var(--monster-color-red-3);--monster-color-error-3:var(--monster-color-red-4);--monster-color-error-4:var(--monster-color-red-1);--monster-bg-color-error-1:var(--monster-color-red-5);--monster-bg-color-error-2:var(--monster-color-gray-6);--monster-bg-color-error-3:var(--monster-color-red-1);--monster-bg-color-error-4:var(--monster-color-red-4)}}:after,:before,:root{--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-selection-1:var(--monster-color-gray-6);--monster-color-selection-2:var(--monster-color-gray-6);--monster-color-selection-3:var(--monster-color-gray-6);--monster-color-selection-4:var(--monster-color-gray-1);--monster-bg-color-selection-1:var(--monster-color-yellow-2);--monster-bg-color-selection-2:var(--monster-color-yellow-1);--monster-bg-color-selection-3:var(--monster-color-yellow-2);--monster-bg-color-selection-4:var(--monster-color-yellow-6)}}:after,:before,:root{--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-4);--monster-color-primary-disabled-4:var(--monster-color-gray-4);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-1);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-6);--monster-color-gradient-1:#833ab4;--monster-color-gradient-2:#fd1d1d;--monster-color-gradient-3:#fcb045}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-color-primary-disabled-1:var(--monster-color-gray-4);--monster-color-primary-disabled-2:var(--monster-color-gray-4);--monster-color-primary-disabled-3:var(--monster-color-gray-3);--monster-color-primary-disabled-4:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-1:var(--monster-color-gray-6);--monster-bg-color-primary-disabled-2:var(--monster-color-gray-3);--monster-bg-color-primary-disabled-3:var(--monster-color-gray-2);--monster-bg-color-primary-disabled-4:var(--monster-color-gray-1);--monster-color-gradient-1:#ffe0b2;--monster-color-gradient-2:#ad8275;--monster-color-gradient-3:#771ba3}}:after,:before,:root{--monster-box-shadow-1:none;--monster-box-shadow-2:-1px 1px 10px 1px hsla(0,0%,76%,.61);--monster-text-shadow:none;--monster-theme-control-bg-color:var(--monster-color-seashell-1);--monster-theme-control-color:var(--monster-color-seashell-6);--monster-theme-control-hover-color:var(--monster-color-seashell-6);--monster-theme-control-hover-bg-color:var(--monster-color-seashell-2);--monster-theme-control-border-width:2px;--monster-theme-control-border-style:solid;--monster-theme-control-border-radius:0;--monster-theme-control-border-color:var(--monster-color-primary-1)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-theme-control-bg-color:var(--monster-color-gray-5);--monster-theme-control-color:var(--monster-color-gray-1);--monster-theme-control-border-color:var(--monster-color-gray-3);--monster-theme-control-hover-color:var(--monster-color-gray-1);--monster-theme-control-hover-bg-color:var(--monster-color-gray-6)}}:after,:before,:root{--monster-theme-on-color:var(--monster-color-green-1);--monster-theme-on-bg-color:var(--monster-color-green-5);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-4)}@media (prefers-color-scheme:dark){:after,:before,:root{--monster-theme-on-color:var(--monster-color-gray-6);--monster-theme-on-bg-color:var(--monster-color-gray-1);--monster-theme-off-color:var(--monster-color-gray-1);--monster-theme-off-bg-color:var(--monster-color-gray-5)}}:after,:before,:root{--monster-border-style:solid;--monster-border-width:3px;--monster-border-radius:0;--monster-outline-width:1px;--monster-popper-witharrrow-distance:-4px;--monster-z-index-default:0;--monster-z-index-outline:10;--monster-z-index-dropdown:200;--monster-z-index-dropdown-overlay:210;--monster-z-index-sticky:300;--monster-z-index-sticky-overlay:310;--monster-z-index-fixed:400;--monster-z-index-fixed-overlay:410;--monster-z-index-modal-backdrop:500;--monster-z-index-modal-backdrop-overlay:510;--monster-z-index-offcanvas:600;--monster-z-index-offcanvas-overlay:610;--monster-z-index-modal:700;--monster-z-index-modal-overlay:710;--monster-z-index-popover:800;--monster-z-index-popover-overlay:810;--monster-z-index-tooltip:800;--monster-z-index-tooltip-overlay:910;--monster-space-0:0;--monster-space-1:2px;--monster-space-2:4px;--monster-space-3:6px;--monster-space-4:10px;--monster-space-5:16px;--monster-space-6:26px;--monster-space-7:42px;--monster-breakpoint-0:480px;--monster-breakpoint-4:480px;--monster-breakpoint-7:768px;--monster-breakpoint-9:992px;--monster-breakpoint-12:1200px;--monster-dragger-width:2px;--monster-dragger-handle-width:4px;--monster-dragger-handle-height:50px}div[data-monster-role=popper]{align-content:center;background:var(--monster-bg-color-primary-1);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);box-sizing:border-box;color:var(--monster-color-primary-1);display:none;justify-content:space-between;left:0;padding:1.1em;position:absolute;top:0;width:-moz-max-content;width:max-content;z-index:var(--monster-z-index-modal)}div[data-monster-role=popper] div[data-monster-role=arrow]{background:var(--monster-bg-color-primary-1);height:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);pointer-events:none;position:absolute;width:calc(max(var(--monster-popper-witharrrow-distance), -1 * var(--monster-popper-witharrrow-distance))*2);z-index:-1}[data-monster-role=control]{background-color:var(--monster-color-primary-4);border-color:var(--monster-bg-color-primary-4);border-radius:var(--monster-border-radius);border-style:var(--monster-border-style);border-width:var(--monster-border-width);box-shadow:var(--monster-box-shadow-1);color:var(--monster-bg-color-primary-4);display:flex;flex-direction:column;justify-content:flex-end;margin:0;padding:0;position:relative}[data-monster-role=full-screen]{position:absolute;right:1rem;top:1rem;z-index:var(--monster-z-index-dropdown)}.camera-not-supported-text{background-color:var(--monster-bg-color-primary-1);color:var(--monster-color-primary-1);font-size:1.2rem;font-weight:600;margin:0;padding:1rem;text-align:center}canvas,video{display:block;max-height:100%;max-width:100%}monster-button::part(button){border:none}
28
- }`, 0);
29
+ }`,
30
+ 0,
31
+ );
29
32
  } catch (e) {
30
- addAttributeToken(document.getRootNode().querySelector('html'), ATTRIBUTE_ERRORMESSAGE, e + "");
33
+ addAttributeToken(
34
+ document.getRootNode().querySelector("html"),
35
+ ATTRIBUTE_ERRORMESSAGE,
36
+ e + "",
37
+ );
31
38
  }
@@ -0,0 +1,473 @@
1
+ /**
2
+ * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
3
+ * Node module: @schukai/monster
4
+ *
5
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
6
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
7
+ *
8
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
9
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
10
+ * For more information about purchasing a commercial license, please contact schukai GmbH.
11
+ */
12
+
13
+ import { instanceSymbol } from "../../constants.mjs";
14
+ import { addAttributeToken } from "../../dom/attributes.mjs";
15
+ import {
16
+ ATTRIBUTE_ERRORMESSAGE,
17
+ ATTRIBUTE_ROLE,
18
+ } from "../../dom/constants.mjs";
19
+ import {
20
+ CustomElement,
21
+ updaterTransformerMethodsSymbol,
22
+ } from "../../dom/customelement.mjs";
23
+ import {
24
+ assembleMethodSymbol,
25
+ registerCustomElement,
26
+ } from "../../dom/customelement.mjs";
27
+ import { findTargetElementFromEvent } from "../../dom/events.mjs";
28
+ import { isFunction, isString } from "../../types/is.mjs";
29
+ import { MetricGraphStyleSheet } from "./stylesheet/metric-graph.mjs";
30
+ import { fireCustomEvent } from "../../dom/events.mjs";
31
+
32
+ export { MetricGraph };
33
+
34
+ /**
35
+ * @private
36
+ * @type {symbol}
37
+ */
38
+ export const metricGraphControlElementSymbol = Symbol(
39
+ "metricGraphControlElement",
40
+ );
41
+
42
+ /**
43
+ * A MetricGraph
44
+ *
45
+ * @fragments /fragments/data/metric-graph/
46
+ *
47
+ * @example /examples/data/metric-graph-simple
48
+ *
49
+ * @since 4.11.0
50
+ * @copyright schukai GmbH
51
+ * @summary A beautiful MetricGraph that can make your life easier and also looks good.
52
+ */
53
+ class MetricGraph extends CustomElement {
54
+ /**
55
+ * This method is called by the `instanceof` operator.
56
+ * @returns {symbol}
57
+ */
58
+ static get [instanceSymbol]() {
59
+ return Symbol.for("@schukai/monster/data/metric-graph@@instance");
60
+ }
61
+
62
+ /**
63
+ * @return {Components.Data.Metric
64
+ */
65
+ [assembleMethodSymbol]() {
66
+ super[assembleMethodSymbol]();
67
+ initControlReferences.call(this);
68
+ return this;
69
+ }
70
+
71
+ /**
72
+ * To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
73
+ * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
74
+ *
75
+ * The individual configuration values can be found in the table.
76
+ *
77
+ * @property {Object} templates Template definitions
78
+ * @property {string} templates.main Main template
79
+ * @property {string} curve The curve of the graph (step, smooth, bubble, bar, area, dot, lollipop, line)
80
+ * @property {Object} values Value definitions
81
+ * @property {number} values.value The value of the metric
82
+ * @property {number} values.change The change of the metric
83
+ * @property {number} values.secondary The secondary value of the metric
84
+ * @property {Array} values.points The points of the metric
85
+ * @property {Object} labels Label definitions
86
+ * @property {string} labels.title Title of the metric
87
+ * @property {string} labels.subtext Subtext of the metric
88
+ * @property {Object} classes CSS classes
89
+ * @property {string} classes.dot CSS class for the dot
90
+ */
91
+ get defaults() {
92
+ return Object.assign({}, super.defaults, {
93
+ templates: {
94
+ main: getTemplate(),
95
+ },
96
+
97
+ graphType: "linear",
98
+
99
+ values: {
100
+ main: null,
101
+ change: null,
102
+ secondary: null,
103
+ points: [2, 2, 2, -30, 30, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1],
104
+ },
105
+ labels: {
106
+ title: null,
107
+ subtext: null,
108
+ },
109
+ classes: {
110
+ dot: "monster-theme-primary-1",
111
+ },
112
+
113
+ aria: {
114
+ description: null,
115
+ },
116
+ });
117
+ }
118
+
119
+ /**
120
+ *
121
+ * @returns {{tosparkline: ((function(*): (string|string))|*)}}
122
+ */
123
+ [updaterTransformerMethodsSymbol]() {
124
+ return {
125
+ toGraph: (value) => {
126
+ if (isString(value)) {
127
+ value = value.split(",").map((v) => {
128
+ return parseFloat(v);
129
+ });
130
+ }
131
+
132
+ const graphType = this.getOption("graphType");
133
+
134
+ if (!Array.isArray(value) || value.length === 0) return "";
135
+ switch (graphType.toLowerCase()) {
136
+ case "step":
137
+ return renderStepGraph.call(this, value);
138
+ case "smooth":
139
+ return renderSmoothGraph.call(this, value);
140
+ case "bubble":
141
+ return renderBubbleGraph.call(this, value);
142
+ case "bar":
143
+ return renderBarGraph.call(this, value);
144
+ case "area":
145
+ return renderAreaGraph.call(this, value);
146
+ case "dot":
147
+ return renderDotGraph.call(this, value);
148
+ case "lollipop":
149
+ return renderLollipopGraph.call(this, value);
150
+ case "line":
151
+ default:
152
+ return renderLineGraph.call(this, value);
153
+ }
154
+ },
155
+ };
156
+ }
157
+
158
+ /**
159
+ * @return {string}
160
+ */
161
+ static getTag() {
162
+ return "monster-metric-graph";
163
+ }
164
+
165
+ /**
166
+ * @return {CSSStyleSheet[]}
167
+ */
168
+ static getCSSStyleSheet() {
169
+ return [MetricGraphStyleSheet];
170
+ }
171
+ }
172
+
173
+ function renderAreaGraph(values, options = {}) {
174
+ const {
175
+ width = 100,
176
+ height = 30,
177
+ stroke = "currentColor",
178
+ strokeWidth = 2,
179
+ fill = "rgba(0, 0, 0, 0.1)",
180
+ } = options;
181
+
182
+ if (!Array.isArray(values) || values.length === 0) return "";
183
+
184
+ const min = Math.min(...values);
185
+ const max = Math.max(...values);
186
+ const range = max - min || 1;
187
+
188
+ const step = width / (values.length - 1);
189
+ const points = values.map((v, i) => {
190
+ const x = i * step;
191
+ const y = height - ((v - min) / range) * height;
192
+ return { x, y };
193
+ });
194
+
195
+ let d = `M ${points[0].x},${height} L ${points[0].x},${points[0].y}`;
196
+ for (let i = 1; i < points.length; i++) {
197
+ d += ` L ${points[i].x},${points[i].y}`;
198
+ }
199
+ d += ` L ${points[points.length - 1].x},${height} Z`;
200
+
201
+ return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linejoin="round" />`;
202
+ }
203
+
204
+ function renderBubbleGraph(values, options = {}) {
205
+ const {
206
+ width = 100,
207
+ height = 30,
208
+ minRadius = 2,
209
+ maxRadius = 8,
210
+ lightRange = [0.3, 1.0], // fill-opacity von 0.3 bis 1.0
211
+ align = "middle",
212
+ } = options;
213
+
214
+ if (!Array.isArray(values) || values.length === 0) return "";
215
+
216
+ const min = Math.min(...values);
217
+ const max = Math.max(...values);
218
+ const range = max - min || 1;
219
+
220
+ const stepX = width / values.length;
221
+
222
+ let centerY;
223
+ switch (align) {
224
+ case "top":
225
+ centerY = maxRadius;
226
+ break;
227
+ case "bottom":
228
+ centerY = height - maxRadius;
229
+ break;
230
+ case "middle":
231
+ default:
232
+ centerY = height / 2;
233
+ }
234
+
235
+ return values
236
+ .map((v, i) => {
237
+ const x = i * stepX + stepX / 2;
238
+ const norm = (v - min) / range;
239
+ const r = minRadius + norm * (maxRadius - minRadius);
240
+ const opacity = lightRange[0] + norm * (lightRange[1] - lightRange[0]);
241
+
242
+ return `<circle cx="${x.toFixed(2)}" cy="${centerY.toFixed(2)}" r="${r.toFixed(2)}" fill="currentColor" fill-opacity="${opacity.toFixed(2)}" />`;
243
+ })
244
+ .join("");
245
+ }
246
+
247
+ function renderLollipopGraph(values, options = {}) {
248
+ const {
249
+ width = 100,
250
+ height = 30,
251
+ color = "currentColor",
252
+ radius = 2,
253
+ strokeWidth = 1,
254
+ } = options;
255
+
256
+ if (!Array.isArray(values) || values.length === 0) return "";
257
+
258
+ const min = Math.min(...values);
259
+ const max = Math.max(...values);
260
+ const range = max - min || 1;
261
+
262
+ const step = width / (values.length - 1);
263
+
264
+ return values
265
+ .map((v, i) => {
266
+ const x = i * step;
267
+ const y = height - ((v - min) / range) * height;
268
+ const line = `<line x1="${x}" y1="${height}" x2="${x}" y2="${y}" stroke="${color}" stroke-width="${strokeWidth}" />`;
269
+ const circle = `<circle cx="${x}" cy="${y}" r="${radius}" fill="${color}" />`;
270
+ return line + circle;
271
+ })
272
+ .join("");
273
+ }
274
+
275
+ function renderDotGraph(values, options = {}) {
276
+ const {
277
+ width = 100,
278
+ height = 30,
279
+ radius = 2,
280
+ color = "currentColor",
281
+ } = options;
282
+
283
+ if (!Array.isArray(values) || values.length === 0) return "";
284
+
285
+ const min = Math.min(...values);
286
+ const max = Math.max(...values);
287
+ const range = max - min || 1;
288
+
289
+ const step = width / (values.length - 1);
290
+
291
+ return values
292
+ .map((v, i) => {
293
+ const x = i * step;
294
+ const y = height - ((v - min) / range) * height;
295
+ return `<circle cx="${x.toFixed(2)}" cy="${y.toFixed(2)}" r="${radius}" fill="${color}" />`;
296
+ })
297
+ .join("");
298
+ }
299
+
300
+ function renderBarGraph(values, options = {}) {
301
+ const {
302
+ width = 100,
303
+ height = 30,
304
+ barColor = "currentColor",
305
+ barSpacing = 1,
306
+ } = options;
307
+
308
+ if (!Array.isArray(values) || values.length === 0) return "";
309
+
310
+ const min = Math.min(...values);
311
+ const max = Math.max(...values);
312
+ const range = max - min || 1;
313
+
314
+ const barWidth = width / values.length - barSpacing;
315
+
316
+ return values
317
+ .map((v, i) => {
318
+ const x = i * (barWidth + barSpacing);
319
+ const barHeight = ((v - min) / range) * height;
320
+ const y = height - barHeight;
321
+ return `<rect x="${x.toFixed(2)}" y="${y.toFixed(2)}" width="${barWidth.toFixed(2)}" height="${barHeight.toFixed(2)}" fill="${barColor}" />`;
322
+ })
323
+ .join("");
324
+ }
325
+
326
+ function renderLineGraph(values) {
327
+ if (!Array.isArray(values) || values.length === 0) return "";
328
+ const min = Math.min(...values);
329
+ const max = Math.max(...values);
330
+ const range = max - min || 1;
331
+
332
+ const step = 100 / (values.length - 1);
333
+ const points = values.map((v, i) => {
334
+ const x = i * step;
335
+ const y = 30 - ((v - min) / range) * 30;
336
+ return `${x},${y}`;
337
+ });
338
+
339
+ return `<polyline points="${points.join(" ")}" stroke="currentColor" stroke-width="2" fill="none" />`;
340
+ }
341
+
342
+ function renderSmoothGraph(values, options = {}) {
343
+ const {
344
+ width = 100,
345
+ height = 30,
346
+ stroke = "currentColor",
347
+ strokeWidth = 2,
348
+ fill = "none",
349
+ } = options;
350
+
351
+ if (!Array.isArray(values) || values.length === 0) return "";
352
+
353
+ const min = Math.min(...values);
354
+ const max = Math.max(...values);
355
+ const range = max - min || 1;
356
+
357
+ const stepX = width / (values.length - 1);
358
+
359
+ const points = values.map((v, i) => {
360
+ const x = i * stepX;
361
+ const y = height - ((v - min) / range) * height;
362
+ return { x, y };
363
+ });
364
+
365
+ // Bézier-Path erzeugen
366
+ let d = `M ${points[0].x},${points[0].y}`;
367
+ for (let i = 1; i < points.length; i++) {
368
+ const prev = points[i - 1];
369
+ const curr = points[i];
370
+ const cx = (prev.x + curr.x) / 2;
371
+ d += ` Q ${prev.x},${prev.y} ${cx},${(prev.y + curr.y) / 2}`;
372
+ }
373
+ d += ` T ${points[points.length - 1].x},${points[points.length - 1].y}`;
374
+
375
+ return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linecap="round" stroke-linejoin="round" />`;
376
+ }
377
+
378
+ function renderStepGraph(values, options = {}) {
379
+ const {
380
+ width = 100,
381
+ height = 30,
382
+ stroke = "currentColor",
383
+ strokeWidth = 2,
384
+ fill = "none",
385
+ } = options;
386
+
387
+ if (!Array.isArray(values) || values.length === 0) return "";
388
+
389
+ const min = Math.min(...values);
390
+ const max = Math.max(...values);
391
+ const range = max - min || 1;
392
+
393
+ const stepX = width / (values.length - 1);
394
+
395
+ const points = values.map((v, i) => {
396
+ const x = i * stepX;
397
+ const y = height - ((v - min) / range) * height;
398
+ return { x, y };
399
+ });
400
+
401
+ let d = `M ${points[0].x},${points[0].y}`;
402
+ for (let i = 1; i < points.length; i++) {
403
+ const prev = points[i - 1];
404
+ const curr = points[i];
405
+ d += ` H ${curr.x} V ${curr.y}`;
406
+ }
407
+
408
+ return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linecap="round" stroke-linejoin="round" />`;
409
+ }
410
+
411
+ /**
412
+ * @private
413
+ * @return {void}
414
+ */
415
+ function initControlReferences() {
416
+ this[metricGraphControlElementSymbol] = this.shadowRoot.querySelector(
417
+ `[${ATTRIBUTE_ROLE}="control"]`,
418
+ );
419
+ }
420
+
421
+ /**
422
+ * @private
423
+ * @return {string}
424
+ */
425
+ function getTemplate() {
426
+ // language=HTML
427
+ return `
428
+ <div data-monster-role="control"
429
+ part="control"
430
+ role="group"
431
+ aria-labelledby="metric-title"
432
+ aria-describedby="metric-value metric-subtext metric-graph-desc">
433
+
434
+ <div class="metric-card" part="card">
435
+ <div class="metric-header" part="header">
436
+ <span data-monster-attributes="class path:classes.dot | prefix:metric-icon\\ :"></span>
437
+ <span id="metric-title" class="metric-title"
438
+ data-monster-replace="path:labels.title | ??:—"></span>
439
+ </div>
440
+
441
+ <div id="metric-value" class="metric-value"
442
+ data-monster-replace="path:values.main"
443
+ part="metric-value"
444
+ aria-live="polite">—</div>
445
+
446
+ <div id="metric-subtext" class="metric-subtext" part="metric-subtext">
447
+ <span data-monster-replace="path:labels.subtext | ??:— ">—</span><br>
448
+ <span class="metric-subtext-value">
449
+ <strong data-monster-replace="path:values.secondary | ??:—">—</strong>
450
+ </span>
451
+ </div>
452
+
453
+ <div part="metric-graph" class="metric-graph">
454
+ <svg viewBox="0 0 100 30"
455
+ preserveAspectRatio="none"
456
+ role="img"
457
+ aria-labelledby="metric-graph-desc"
458
+ focusable="false"
459
+ xmlns="http://www.w3.org/2000/svg"
460
+ data-monster-replace="path:values.points | call:toGraph">
461
+ </svg>
462
+ <span id="metric-graph-desc" class="visually-hidden"
463
+ data-monster-replace="path:aria.graph | ??:Graphische Darstellung der Kennzahl">
464
+ Graphische Darstellung
465
+ </span>
466
+ </div>
467
+ </div>
468
+
469
+ <span class="visually-hidden" data-monster-replace="path:aria.description"></span>
470
+ </div>`;
471
+ }
472
+
473
+ registerCustomElement(MetricGraph);