@schukai/monster 4.11.0 → 4.12.0

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,421 +10,421 @@
10
10
  * For more information about purchasing a commercial license, please contact schukai GmbH.
11
11
  */
12
12
 
13
- import {instanceSymbol} from "../../constants.mjs";
14
- import {addAttributeToken} from "../../dom/attributes.mjs";
13
+ import { instanceSymbol } from "../../constants.mjs";
14
+ import { addAttributeToken } from "../../dom/attributes.mjs";
15
15
  import {
16
- ATTRIBUTE_ERRORMESSAGE,
17
- ATTRIBUTE_ROLE,
16
+ ATTRIBUTE_ERRORMESSAGE,
17
+ ATTRIBUTE_ROLE,
18
18
  } from "../../dom/constants.mjs";
19
- import {CustomElement, updaterTransformerMethodsSymbol} from "../../dom/customelement.mjs";
20
19
  import {
21
- assembleMethodSymbol,
22
- registerCustomElement,
20
+ CustomElement,
21
+ updaterTransformerMethodsSymbol,
23
22
  } from "../../dom/customelement.mjs";
24
- import {findTargetElementFromEvent} from "../../dom/events.mjs";
25
- import {isFunction, isString} from "../../types/is.mjs";
26
- import {MetricGraphStyleSheet} from "./stylesheet/metric-graph.mjs";
27
- import {fireCustomEvent} from "../../dom/events.mjs";
28
-
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";
29
31
 
30
- export {MetricGraph};
32
+ export { MetricGraph };
31
33
 
32
34
  /**
33
35
  * @private
34
36
  * @type {symbol}
35
37
  */
36
- export const metricGraphControlElementSymbol = Symbol("metricGraphControlElement");
38
+ export const metricGraphControlElementSymbol = Symbol(
39
+ "metricGraphControlElement",
40
+ );
37
41
 
38
42
  /**
39
43
  * A MetricGraph
40
44
  *
41
- * @fragments /fragments/data/metric-graph/
45
+ * @fragments /fragments/components/data/metric-graph/
42
46
  *
43
- * @example /examples/data/metric-graph-simple
47
+ * @example /examples/components/data/metric-graph-simple
44
48
  *
45
49
  * @since 4.11.0
46
50
  * @copyright schukai GmbH
47
51
  * @summary A beautiful MetricGraph that can make your life easier and also looks good.
48
52
  */
49
53
  class MetricGraph extends CustomElement {
50
- /**
51
- * This method is called by the `instanceof` operator.
52
- * @returns {symbol}
53
- */
54
- static get [instanceSymbol]() {
55
- return Symbol.for("@schukai/monster/data/metric-graph@@instance");
56
- }
57
-
58
- /**
59
- * @return {Components.Data.Metric
60
- */
61
- [assembleMethodSymbol]() {
62
- super[assembleMethodSymbol]();
63
- initControlReferences.call(this);
64
- return this;
65
- }
66
-
67
- /**
68
- * To set the options via the HTML Tag, the attribute `data-monster-options` must be used.
69
- * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
70
- *
71
- * The individual configuration values can be found in the table.
72
- *
73
- * @property {Object} templates Template definitions
74
- * @property {string} templates.main Main template
75
- * @property {string} curve The curve of the graph (step, smooth, bubble, bar, area, dot, lollipop, line)
76
- * @property {Object} values Value definitions
77
- * @property {number} values.value The value of the metric
78
- * @property {number} values.change The change of the metric
79
- * @property {number} values.secondary The secondary value of the metric
80
- * @property {Array} values.points The points of the metric
81
- * @property {Object} labels Label definitions
82
- * @property {string} labels.title Title of the metric
83
- * @property {string} labels.subtext Subtext of the metric
84
- * @property {Object} classes CSS classes
85
- * @property {string} classes.dot CSS class for the dot
86
- */
87
- get defaults() {
88
- return Object.assign({}, super.defaults, {
89
- templates: {
90
- main: getTemplate(),
91
- },
92
-
93
- graphType: "linear",
94
-
95
- values: {
96
- main: null,
97
- change: null,
98
- secondary: null,
99
- points: [2, 2, 2, -30, 30, 5, 4,4, 3, 3, 2,2, 1, 1, 1, 1],
100
- },
101
- labels: {
102
- title: null,
103
- subtext: null,
104
-
105
- },
106
- classes: {
107
- dot: "monster-theme-primary-1"
108
- },
109
-
110
- aria : {
111
- description: null,
112
- }
113
-
114
- });
115
- }
116
-
117
-
118
- /**
119
- *
120
- * @returns {{tosparkline: ((function(*): (string|string))|*)}}
121
- */
122
- [updaterTransformerMethodsSymbol]() {
123
-
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
- /**
160
- * @return {string}
161
- */
162
- static getTag() {
163
- return "monster-metric-graph";
164
- }
165
-
166
- /**
167
- * @return {CSSStyleSheet[]}
168
- */
169
- static getCSSStyleSheet() {
170
- return [MetricGraphStyleSheet];
171
- }
172
-
173
-
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 {MetricGraph}
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
+ }
174
171
  }
175
172
 
176
173
  function renderAreaGraph(values, options = {}) {
177
- const {
178
- width = 100,
179
- height = 30,
180
- stroke = "currentColor",
181
- strokeWidth = 2,
182
- fill = "rgba(0, 0, 0, 0.1)",
183
- } = options;
184
-
185
- if (!Array.isArray(values) || values.length === 0) return "";
186
-
187
- const min = Math.min(...values);
188
- const max = Math.max(...values);
189
- const range = max - min || 1;
190
-
191
- const step = width / (values.length - 1);
192
- const points = values.map((v, i) => {
193
- const x = i * step;
194
- const y = height - ((v - min) / range) * height;
195
- return { x, y };
196
- });
197
-
198
- let d = `M ${points[0].x},${height} L ${points[0].x},${points[0].y}`;
199
- for (let i = 1; i < points.length; i++) {
200
- d += ` L ${points[i].x},${points[i].y}`;
201
- }
202
- d += ` L ${points[points.length - 1].x},${height} Z`;
203
-
204
- return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linejoin="round" />`;
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" />`;
205
202
  }
206
203
 
207
204
  function renderBubbleGraph(values, options = {}) {
208
- const {
209
- width = 100,
210
- height = 30,
211
- minRadius = 2,
212
- maxRadius = 8,
213
- lightRange = [0.3, 1.0], // fill-opacity von 0.3 bis 1.0
214
- align = "middle",
215
- } = options;
216
-
217
- if (!Array.isArray(values) || values.length === 0) return "";
218
-
219
- const min = Math.min(...values);
220
- const max = Math.max(...values);
221
- const range = max - min || 1;
222
-
223
- const stepX = width / values.length;
224
-
225
- let centerY;
226
- switch (align) {
227
- case "top": centerY = maxRadius; break;
228
- case "bottom": centerY = height - maxRadius; break;
229
- case "middle":
230
- default: centerY = height / 2;
231
- }
232
-
233
- return values.map((v, i) => {
234
- const x = i * stepX + stepX / 2;
235
- const norm = (v - min) / range;
236
- const r = minRadius + norm * (maxRadius - minRadius);
237
- const opacity = lightRange[0] + norm * (lightRange[1] - lightRange[0]);
238
-
239
- return `<circle cx="${x.toFixed(2)}" cy="${centerY.toFixed(2)}" r="${r.toFixed(2)}" fill="currentColor" fill-opacity="${opacity.toFixed(2)}" />`;
240
- }).join("");
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("");
241
245
  }
242
246
 
243
-
244
-
245
-
246
247
  function renderLollipopGraph(values, options = {}) {
247
- const {
248
- width = 100,
249
- height = 30,
250
- color = "currentColor",
251
- radius = 2,
252
- strokeWidth = 1,
253
- } = options;
254
-
255
- if (!Array.isArray(values) || values.length === 0) return "";
256
-
257
- const min = Math.min(...values);
258
- const max = Math.max(...values);
259
- const range = max - min || 1;
260
-
261
- const step = width / (values.length - 1);
262
-
263
- return values.map((v, i) => {
264
- const x = i * step;
265
- const y = height - ((v - min) / range) * height;
266
- const line = `<line x1="${x}" y1="${height}" x2="${x}" y2="${y}" stroke="${color}" stroke-width="${strokeWidth}" />`;
267
- const circle = `<circle cx="${x}" cy="${y}" r="${radius}" fill="${color}" />`;
268
- return line + circle;
269
- }).join("");
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("");
270
273
  }
271
274
 
272
-
273
275
  function renderDotGraph(values, options = {}) {
274
- const {
275
- width = 100,
276
- height = 30,
277
- radius = 2,
278
- color = "currentColor",
279
- } = options;
280
-
281
- if (!Array.isArray(values) || values.length === 0) return "";
282
-
283
- const min = Math.min(...values);
284
- const max = Math.max(...values);
285
- const range = max - min || 1;
286
-
287
- const step = width / (values.length - 1);
288
-
289
- return values.map((v, i) => {
290
- const x = i * step;
291
- const y = height - ((v - min) / range) * height;
292
- return `<circle cx="${x.toFixed(2)}" cy="${y.toFixed(2)}" r="${radius}" fill="${color}" />`;
293
- }).join("");
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("");
294
298
  }
295
299
 
296
-
297
-
298
300
  function renderBarGraph(values, options = {}) {
299
- const {
300
- width = 100,
301
- height = 30,
302
- barColor = "currentColor",
303
- barSpacing = 1,
304
- } = options;
305
-
306
- if (!Array.isArray(values) || values.length === 0) return "";
307
-
308
- const min = Math.min(...values);
309
- const max = Math.max(...values);
310
- const range = max - min || 1;
311
-
312
- const barWidth = width / values.length - barSpacing;
313
-
314
- return values
315
- .map((v, i) => {
316
- const x = i * (barWidth + barSpacing);
317
- const barHeight = ((v - min) / range) * height;
318
- const y = height - barHeight;
319
- return `<rect x="${x.toFixed(2)}" y="${y.toFixed(2)}" width="${barWidth.toFixed(2)}" height="${barHeight.toFixed(2)}" fill="${barColor}" />`;
320
- })
321
- .join("");
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("");
322
324
  }
323
325
 
324
326
  function renderLineGraph(values) {
325
- if (!Array.isArray(values) || values.length === 0) return "";
326
- const min = Math.min(...values);
327
- const max = Math.max(...values);
328
- const range = max - min || 1;
329
-
330
- const step = 100 / (values.length - 1);
331
- const points = values.map((v, i) => {
332
- const x = i * step;
333
- const y = 30 - ((v - min) / range) * 30;
334
- return `${x},${y}`;
335
- });
336
-
337
- return `<polyline points="${points.join(" ")}" stroke="currentColor" stroke-width="2" fill="none" />`;
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" />`;
338
340
  }
339
341
 
340
342
  function renderSmoothGraph(values, options = {}) {
341
- const {
342
- width = 100,
343
- height = 30,
344
- stroke = "currentColor",
345
- strokeWidth = 2,
346
- fill = "none",
347
- } = options;
348
-
349
- if (!Array.isArray(values) || values.length === 0) return "";
350
-
351
- const min = Math.min(...values);
352
- const max = Math.max(...values);
353
- const range = max - min || 1;
354
-
355
- const stepX = width / (values.length - 1);
356
-
357
- const points = values.map((v, i) => {
358
- const x = i * stepX;
359
- const y = height - ((v - min) / range) * height;
360
- return { x, y };
361
- });
362
-
363
- // Bézier-Path erzeugen
364
- let d = `M ${points[0].x},${points[0].y}`;
365
- for (let i = 1; i < points.length; i++) {
366
- const prev = points[i - 1];
367
- const curr = points[i];
368
- const cx = (prev.x + curr.x) / 2;
369
- d += ` Q ${prev.x},${prev.y} ${cx},${(prev.y + curr.y) / 2}`;
370
- }
371
- d += ` T ${points[points.length - 1].x},${points[points.length - 1].y}`;
372
-
373
- return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linecap="round" stroke-linejoin="round" />`;
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" />`;
374
376
  }
375
377
 
376
378
  function renderStepGraph(values, options = {}) {
377
- const {
378
- width = 100,
379
- height = 30,
380
- stroke = "currentColor",
381
- strokeWidth = 2,
382
- fill = "none",
383
- } = options;
384
-
385
- if (!Array.isArray(values) || values.length === 0) return "";
386
-
387
- const min = Math.min(...values);
388
- const max = Math.max(...values);
389
- const range = max - min || 1;
390
-
391
- const stepX = width / (values.length - 1);
392
-
393
- const points = values.map((v, i) => {
394
- const x = i * stepX;
395
- const y = height - ((v - min) / range) * height;
396
- return { x, y };
397
- });
398
-
399
- let d = `M ${points[0].x},${points[0].y}`;
400
- for (let i = 1; i < points.length; i++) {
401
- const prev = points[i - 1];
402
- const curr = points[i];
403
- d += ` H ${curr.x} V ${curr.y}`;
404
- }
405
-
406
- return `<path d="${d}" stroke="${stroke}" stroke-width="${strokeWidth}" fill="${fill}" stroke-linecap="round" stroke-linejoin="round" />`;
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" />`;
407
409
  }
408
410
 
409
-
410
411
  /**
411
412
  * @private
412
413
  * @return {void}
413
414
  */
414
415
  function initControlReferences() {
415
- this[metricGraphControlElementSymbol] = this.shadowRoot.querySelector(
416
- `[${ATTRIBUTE_ROLE}="control"]`,
417
- );
416
+ this[metricGraphControlElementSymbol] = this.shadowRoot.querySelector(
417
+ `[${ATTRIBUTE_ROLE}="control"]`,
418
+ );
418
419
  }
419
420
 
420
-
421
421
  /**
422
422
  * @private
423
423
  * @return {string}
424
424
  */
425
425
  function getTemplate() {
426
- // language=HTML
427
- return `
426
+ // language=HTML
427
+ return `
428
428
  <div data-monster-role="control"
429
429
  part="control"
430
430
  role="group"
@@ -470,6 +470,4 @@ function getTemplate() {
470
470
  </div>`;
471
471
  }
472
472
 
473
-
474
-
475
473
  registerCustomElement(MetricGraph);