@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.
- package/CHANGELOG.md +29 -0
- package/package.json +1 -1
- package/source/components/content/camera-capture.mjs +41 -8
- package/source/components/content/stylesheet/camera-capture.mjs +13 -6
- package/source/components/data/metric-graph.mjs +356 -358
- package/source/components/data/metric.mjs +92 -94
- package/source/components/data/stylesheet/metric-graph.mjs +13 -6
- package/source/components/data/stylesheet/metric.mjs +13 -6
- package/source/components/datatable/filter.mjs +22 -0
- package/source/components/form/message-state-button.mjs +26 -22
- package/source/components/layout/popper.mjs +75 -68
- package/source/components/layout/split-panel.mjs +15 -8
- package/source/i18n/util.mjs +41 -0
- package/source/monster.mjs +3 -0
- package/source/text/generate-range-comparison-expression.mjs +109 -39
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/cases/text/generate-range-comparison-expression.mjs +94 -0
- package/test/cases/text/util.mjs +3 -3
- package/test/web/import.js +1 -0
- package/test/web/test.html +2 -2
- package/test/web/tests.js +313 -132
@@ -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
|
-
|
17
|
-
|
16
|
+
ATTRIBUTE_ERRORMESSAGE,
|
17
|
+
ATTRIBUTE_ROLE,
|
18
18
|
} from "../../dom/constants.mjs";
|
19
|
-
import {CustomElement, updaterTransformerMethodsSymbol} from "../../dom/customelement.mjs";
|
20
19
|
import {
|
21
|
-
|
22
|
-
|
20
|
+
CustomElement,
|
21
|
+
updaterTransformerMethodsSymbol,
|
23
22
|
} from "../../dom/customelement.mjs";
|
24
|
-
import {
|
25
|
-
|
26
|
-
|
27
|
-
|
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(
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
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
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
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
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
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
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
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
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
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
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
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
|
-
|
416
|
-
|
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
|
-
|
427
|
-
|
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);
|