@record-evolution/widget-value 1.0.10 → 1.0.11

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.
@@ -0,0 +1,56 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * This file was automatically generated by json-schema-to-typescript.
4
+ * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
5
+ * and run json-schema-to-typescript to regenerate this file.
6
+ */
7
+
8
+ export type Title = string;
9
+ export type Subtitle = string;
10
+ /**
11
+ * The label for the value.
12
+ */
13
+ export type Label = string;
14
+ /**
15
+ * The unit of the value. e.g. °C or km/h
16
+ */
17
+ export type Unit = string;
18
+ export type LabelColor = string;
19
+ export type ValueColor = string;
20
+ /**
21
+ * Calculate the average over the given number of newest values. (If pivoted, then per each of the pivot dataseries.) If not specified then the latest value is shown without modification.
22
+ */
23
+ export type AverageLatestValues = number;
24
+ export type Value = number;
25
+ /**
26
+ * You can specify a column in the input data to autogenerate dataseries for each distinct entry in this column. E.g. if you have a table with columns [city, timestamp, temperature] and specify 'city' as pivot column, then you will get a gauge for each city.
27
+ */
28
+ export type PivotColumn = string;
29
+ /**
30
+ * The data used to draw this data series.
31
+ */
32
+ export type Data = {
33
+ value: Value;
34
+ pivot?: PivotColumn;
35
+ [k: string]: unknown;
36
+ }[];
37
+ export type ValueDisplays = {
38
+ label: Label;
39
+ unit?: Unit;
40
+ labelColor?: LabelColor;
41
+ valueColor?: ValueColor;
42
+ averageLatest?: AverageLatestValues;
43
+ data?: Data;
44
+ [k: string]: unknown;
45
+ }[];
46
+
47
+ export interface ValueChartConfiguration {
48
+ settings?: GlobalSettings;
49
+ dataseries?: ValueDisplays;
50
+ [k: string]: unknown;
51
+ }
52
+ export interface GlobalSettings {
53
+ title?: Title;
54
+ subTitle?: Subtitle;
55
+ [k: string]: unknown;
56
+ }
@@ -25,6 +25,7 @@
25
25
  "order": 2,
26
26
  "items": {
27
27
  "type": "object",
28
+ "required": ["label"],
28
29
  "properties": {
29
30
  "label": {
30
31
  "title": "Label",
@@ -41,12 +42,14 @@
41
42
  },
42
43
  "labelColor": {
43
44
  "title": "Label Color",
44
- "type": "color",
45
+ "type": "string",
46
+ "color": true,
45
47
  "order": 3
46
48
  },
47
49
  "valueColor": {
48
50
  "title": "Value Color",
49
- "type": "color",
51
+ "type": "string",
52
+ "color": true,
50
53
  "order": 4
51
54
  },
52
55
  "averageLatest": {
@@ -63,6 +66,7 @@
63
66
  "buffersize": 100,
64
67
  "items": {
65
68
  "type": "object",
69
+ "required": ["value"],
66
70
  "properties": {
67
71
  "value": {
68
72
  "title": "Value",
@@ -1,272 +1,305 @@
1
- import { html, css, LitElement, PropertyValueMap } from 'lit';
1
+ import { html, css, LitElement, PropertyValueMap } from 'lit'
2
2
  import { repeat } from 'lit/directives/repeat.js'
3
- import { property, state } from 'lit/decorators.js';
4
- import { InputData, Data, Dataseries } from './types.js'
3
+ import { property, state } from 'lit/decorators.js'
4
+ import { ValueChartConfiguration } from './definition-schema.js'
5
5
 
6
- export class WidgetValue extends LitElement {
7
-
8
- @property({type: Object})
9
- inputData?: InputData = undefined
10
-
11
- @state()
12
- private dataSets: Map<string, Dataseries> = new Map()
6
+ type Dataseries = Exclude<ValueChartConfiguration['dataseries'], undefined>[number]
7
+ type Data = Exclude<Dataseries['data'], undefined>[number]
13
8
 
14
- @state()
15
- private textActive: boolean = true
9
+ export class WidgetValue extends LitElement {
10
+ @property({ type: Object })
11
+ inputData?: ValueChartConfiguration
16
12
 
17
- @state()
18
- private numberText?: HTMLDivElement[]
13
+ @state()
14
+ private dataSets: Map<string, Dataseries> = new Map()
19
15
 
20
- @state()
21
- private labelText?: HTMLDivElement[]
16
+ @state()
17
+ private textActive: boolean = true
22
18
 
23
- version: string = 'versionplaceholder'
19
+ @state()
20
+ private numberText?: HTMLDivElement[]
24
21
 
25
- resizeObserver: ResizeObserver
22
+ @state()
23
+ private labelText?: HTMLDivElement[]
26
24
 
27
- valueContainer?: HTMLDivElement
28
- boxes?: HTMLDivElement[]
29
- origWidth: number = 0
30
- origHeight: number = 0
31
- constructor() {
32
- super()
25
+ version: string = 'versionplaceholder'
33
26
 
34
- this.resizeObserver = new ResizeObserver((ev) => this.adjustSizes())
35
- this.resizeObserver.observe(this)
36
- }
27
+ resizeObserver: ResizeObserver
37
28
 
38
- protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) {
39
- this.applyInputData()
40
- }
29
+ valueContainer?: HTMLDivElement
30
+ boxes?: HTMLDivElement[]
31
+ origWidth: number = 0
32
+ origHeight: number = 0
33
+ constructor() {
34
+ super()
41
35
 
42
- update(changedProperties: Map<string, any>) {
43
- changedProperties.forEach((oldValue, propName) => {
44
- if (propName === 'inputData') {
45
- this.applyInputData()
46
- }
47
- })
48
-
49
- this.sizingSetup()
50
-
51
- super.update(changedProperties)
52
- }
53
-
54
- sizingSetup() {
55
- if (this.origWidth !== 0 && this.origHeight !== 0) return
56
-
57
- this.boxes = Array.from(this?.shadowRoot?.querySelectorAll('.single-value') as NodeListOf<HTMLDivElement>)
58
- this.numberText = Array.from(this?.shadowRoot?.querySelectorAll('.current-value') as NodeListOf<HTMLDivElement>)
59
- this.labelText = Array.from(this?.shadowRoot?.querySelectorAll('.label') as NodeListOf<HTMLDivElement>)
60
- this.valueContainer = this?.shadowRoot?.querySelector('.value-container') as HTMLDivElement
61
-
62
- this.origWidth = this.boxes?.map(b => b.getBoundingClientRect().width).reduce((p, c) => c > p ? c : p, 0 ) ?? 0
63
- this.origHeight = this.boxes?.map(b => b.getBoundingClientRect().height).reduce((p, c) => c > p ? c : p, 0 ) ?? 0
64
- if (this.origWidth > 0) this.origWidth += 16
65
- if (this.origHeight > 0) this.origHeight += 16
66
-
67
- this.adjustSizes()
68
-
69
- }
70
-
71
- adjustSizes() {
72
- const userWidth = this.valueContainer?.getBoundingClientRect().width
73
- const userHeight = this.valueContainer?.getBoundingClientRect().height
74
- const count = this.dataSets.size
75
-
76
- const width = this.origWidth
77
- const height = this.origHeight
78
- if (!userWidth || !userHeight || !width || !height) return
79
-
80
- const fits = []
81
- for (let c = 1; c <= count; c++) {
82
- const r = Math.ceil(count/c)
83
- const uwgap = (userWidth - 12 * (c-1))
84
- const uhgap = (userHeight - 12 * (r-1))
85
- const m = uwgap / width / c
86
- const size = m * m * width * height * count
87
- if (r * m * height < uhgap) fits.push({c, m, size, width, height, userWidth, userHeight})
36
+ this.resizeObserver = new ResizeObserver((ev) => this.adjustSizes())
37
+ this.resizeObserver.observe(this)
88
38
  }
89
39
 
90
- for (let r = 1; r <= count; r++) {
91
- const c = Math.ceil(count/r)
92
- const uwgap = (userWidth - 12 * (c-1))
93
- const uhgap = (userHeight - 12 * (r-1))
94
- const m = uhgap / height / r
95
- const size = m * m * width * height * count
96
- if (c * m * width < uwgap) fits.push({r, m, size, width, height, userWidth, userHeight})
40
+ protected firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>) {
41
+ this.applyInputData()
97
42
  }
98
43
 
99
- const maxSize = fits.reduce((p, c) => c.size < p ? p : c.size, 0)
100
- const fit = fits.find(f => f.size === maxSize)
101
- const modifier = (fit?.m ?? 1)
102
- // console.log('FITS', fits, 'modifier', modifier, 'cols',fit?.c, 'rows', fit?.r, 'new size', fit?.size.toFixed(0), 'total space', (userWidth* userHeight).toFixed(0))
103
-
104
- this.boxes?.forEach(box => box.setAttribute("style", `width:${modifier*width}px; height:${modifier*height}px; padding:${modifier*6}px`))
105
- this.numberText?.forEach(n => {
106
- const label: string | null = n.getAttribute('label')
107
- const ds: Dataseries | undefined = this.dataSets.get(label ?? '')
108
- n.setAttribute("style", `font-size: ${(ds?.valueFontSize ?? 32) * modifier}px; ${ds?.valueColor ? "color: " + ds?.valueColor: ''}`)
109
- })
110
-
111
- this.labelText?.forEach(n => {
112
- const label: string | null = n.getAttribute('label')
113
- const ds: Dataseries | undefined = this.dataSets.get(label ?? '')
114
- n.setAttribute("style", `font-size: ${(ds?.labelFontSize ?? 26) * modifier}px; ${ds?.labelColor ? "color: " + ds?.labelColor: ''}`)
115
- })
116
-
117
- this.textActive = true
118
-
119
- }
120
-
121
- async applyInputData() {
122
-
123
- if(!this.inputData) return
124
-
125
- this.dataSets = new Map()
126
- this.inputData.dataseries.sort((a, b) => a.order - b.order).forEach(ds => {
127
-
128
- // pivot data
129
- const distincts = [...new Set(ds.data.map((d: Data) => d.pivot))]
130
- if (distincts.length > 1 || distincts[0] !== undefined) {
131
- distincts.forEach((piv) => {
132
- const pds: any = {
133
- label: `${ds.label} ${piv}`,
134
- order: ds.order,
135
- unit: ds.unit,
136
- averageLatest: ds.averageLatest,
137
- labelColor: ds.labelColor,
138
- valueColor: ds.valueColor,
139
- data: ds.data.filter(d => d.pivot === piv)
140
- }
141
- this.dataSets.set(pds.label, pds)
44
+ update(changedProperties: Map<string, any>) {
45
+ changedProperties.forEach((oldValue, propName) => {
46
+ if (propName === 'inputData') {
47
+ this.applyInputData()
48
+ }
142
49
  })
143
- } else {
144
- this.dataSets.set(ds.label, ds)
145
- }
146
- })
147
-
148
- // filter latest values and calculate average
149
- this.dataSets.forEach((ds, label) => {
150
- if (typeof ds.averageLatest !== 'number' || !isNaN(ds.averageLatest)) ds.averageLatest = 1
151
- ds.data = ds.data.splice(-ds.averageLatest ?? -1)
152
- ds.needleValue = ds.data.map(d => d.value).reduce(( p, c ) => p + c, 0) / ds.data.length
153
- })
154
-
155
- this.requestUpdate(); await this.updateComplete
156
-
157
- // console.log('Value Datasets', this.dataSets)
158
-
159
- }
160
-
161
- static styles = css`
162
- :host {
163
- display: block;
164
- font-family: sans-serif;
165
- box-sizing: border-box;
166
- position: relative;
167
- margin: auto;
168
- }
169
50
 
170
- .paging:not([active]) { display: none !important; }
51
+ this.sizingSetup()
171
52
 
172
- .wrapper {
173
- display: flex;
174
- flex-direction: column;
175
- height: 100%;
176
- width: 100%;
177
- padding: 16px;
178
- box-sizing: border-box;
53
+ super.update(changedProperties)
179
54
  }
180
55
 
181
- h3 {
182
- margin: 0;
183
- max-width: 300px;
184
- overflow: hidden;
185
- text-overflow: ellipsis;
186
- white-space: nowrap;
187
- color: var(--re-text-color, #000) !important;
188
- }
189
- p {
190
- margin: 10px 0 0 0;
191
- max-width: 300px;
192
- font-size: 14px;
193
- line-height: 17px;
194
- overflow: hidden;
195
- text-overflow: ellipsis;
196
- white-space: nowrap;
197
- color: var(--re-text-color, #000) !important;
56
+ sizingSetup() {
57
+ if (this.origWidth !== 0 && this.origHeight !== 0) return
58
+
59
+ this.boxes = Array.from(
60
+ this?.shadowRoot?.querySelectorAll('.single-value') as NodeListOf<HTMLDivElement>
61
+ )
62
+ this.numberText = Array.from(
63
+ this?.shadowRoot?.querySelectorAll('.current-value') as NodeListOf<HTMLDivElement>
64
+ )
65
+ this.labelText = Array.from(
66
+ this?.shadowRoot?.querySelectorAll('.label') as NodeListOf<HTMLDivElement>
67
+ )
68
+ this.valueContainer = this?.shadowRoot?.querySelector('.value-container') as HTMLDivElement
69
+
70
+ this.origWidth =
71
+ this.boxes?.map((b) => b.getBoundingClientRect().width).reduce((p, c) => (c > p ? c : p), 0) ?? 0
72
+ this.origHeight =
73
+ this.boxes?.map((b) => b.getBoundingClientRect().height).reduce((p, c) => (c > p ? c : p), 0) ?? 0
74
+ if (this.origWidth > 0) this.origWidth += 16
75
+ if (this.origHeight > 0) this.origHeight += 16
76
+
77
+ this.adjustSizes()
198
78
  }
199
79
 
200
- .value-container {
201
- display: flex;
202
- flex-wrap: wrap;
203
- align-items: center;
204
- justify-content: center;
205
- flex: 1;
206
- overflow: hidden;
207
- position: relative;
208
- gap: 12px;
209
- }
80
+ adjustSizes() {
81
+ const userWidth = this.valueContainer?.getBoundingClientRect().width
82
+ const userHeight = this.valueContainer?.getBoundingClientRect().height
83
+ const count = this.dataSets.size
84
+
85
+ const width = this.origWidth
86
+ const height = this.origHeight
87
+ if (!userWidth || !userHeight || !width || !height) return
88
+
89
+ const fits = []
90
+ for (let c = 1; c <= count; c++) {
91
+ const r = Math.ceil(count / c)
92
+ const uwgap = userWidth - 12 * (c - 1)
93
+ const uhgap = userHeight - 12 * (r - 1)
94
+ const m = uwgap / width / c
95
+ const size = m * m * width * height * count
96
+ if (r * m * height < uhgap) fits.push({ c, m, size, width, height, userWidth, userHeight })
97
+ }
98
+
99
+ for (let r = 1; r <= count; r++) {
100
+ const c = Math.ceil(count / r)
101
+ const uwgap = userWidth - 12 * (c - 1)
102
+ const uhgap = userHeight - 12 * (r - 1)
103
+ const m = uhgap / height / r
104
+ const size = m * m * width * height * count
105
+ if (c * m * width < uwgap) fits.push({ r, m, size, width, height, userWidth, userHeight })
106
+ }
107
+
108
+ const maxSize = fits.reduce((p, c) => (c.size < p ? p : c.size), 0)
109
+ const fit = fits.find((f) => f.size === maxSize)
110
+ const modifier = fit?.m ?? 1
111
+ // console.log('FITS', fits, 'modifier', modifier, 'cols',fit?.c, 'rows', fit?.r, 'new size', fit?.size.toFixed(0), 'total space', (userWidth* userHeight).toFixed(0))
112
+
113
+ this.boxes?.forEach((box) =>
114
+ box.setAttribute(
115
+ 'style',
116
+ `width:${modifier * width}px; height:${modifier * height}px; padding:${modifier * 6}px`
117
+ )
118
+ )
119
+ this.numberText?.forEach((n) => {
120
+ const label: string | null = n.getAttribute('label')
121
+ const ds: Dataseries | undefined = this.dataSets.get(label ?? '')
122
+ n.setAttribute(
123
+ 'style',
124
+ `font-size: ${32 * modifier}px; ${ds?.valueColor ? 'color: ' + ds?.valueColor : ''}`
125
+ )
126
+ })
127
+
128
+ this.labelText?.forEach((n) => {
129
+ const label: string | null = n.getAttribute('label')
130
+ const ds: Dataseries | undefined = this.dataSets.get(label ?? '')
131
+ n.setAttribute(
132
+ 'style',
133
+ `font-size: ${26 * modifier}px; ${ds?.labelColor ? 'color: ' + ds?.labelColor : ''}`
134
+ )
135
+ })
210
136
 
211
- .single-value {
212
- overflow: hidden;
213
- position: relative;
214
- align-items: end;
215
- font-size: 26px;
216
- padding: 6px;
217
- box-sizing: border-box;
218
- /* border-left: 4px solid #ddd; */
137
+ this.textActive = true
219
138
  }
220
139
 
221
- .current-value {
222
- font-size: 32px;
223
- font-weight: 600;
224
- white-space: nowrap;
225
- color: var(--re-text-color, #000);
140
+ async applyInputData() {
141
+ if (!this.inputData) return
142
+
143
+ this.dataSets = new Map()
144
+ this.inputData?.dataseries
145
+ // ?.sort((a, b) => a.order - b.order)
146
+ ?.forEach((ds) => {
147
+ // pivot data
148
+ const distincts = [...new Set(ds.data?.map((d: Data) => d.pivot))]
149
+ if (distincts.length > 1 || distincts[0] !== undefined) {
150
+ distincts.forEach((piv) => {
151
+ const pds: any = {
152
+ label: `${ds.label} ${piv}`,
153
+ order: ds.order,
154
+ unit: ds.unit,
155
+ averageLatest: ds.averageLatest,
156
+ labelColor: ds.labelColor,
157
+ valueColor: ds.valueColor,
158
+ data: ds.data?.filter((d) => d.pivot === piv)
159
+ }
160
+ this.dataSets.set(pds.label, pds)
161
+ })
162
+ } else {
163
+ this.dataSets.set(ds.label, ds)
164
+ }
165
+ })
166
+
167
+ // filter latest values and calculate average
168
+ this.dataSets.forEach((ds, label) => {
169
+ if (typeof ds.averageLatest !== 'number' || !isNaN(ds.averageLatest)) ds.averageLatest = 1
170
+
171
+ ds.data = ds?.data?.splice(-ds.averageLatest || -1)
172
+ const values = (ds?.data?.map((d) => d.value)?.filter((p) => p !== undefined) ?? []) as number[]
173
+ const average = values.reduce((p, c) => p + c, 0) / values.length
174
+
175
+ ds.needleValue = average
176
+ })
177
+
178
+ this.requestUpdate()
179
+ await this.updateComplete
180
+
181
+ // console.log('Value Datasets', this.dataSets)
226
182
  }
227
183
 
228
- .label {
229
- font-weight: 300;
230
- font-size: 26px;
231
- color: var(--re-text-color, #000);
232
- white-space: nowrap;
184
+ static styles = css`
185
+ :host {
186
+ display: block;
187
+ font-family: sans-serif;
188
+ box-sizing: border-box;
189
+ position: relative;
190
+ margin: auto;
191
+ }
192
+
193
+ .paging:not([active]) {
194
+ display: none !important;
195
+ }
196
+
197
+ .wrapper {
198
+ display: flex;
199
+ flex-direction: column;
200
+ height: 100%;
201
+ width: 100%;
202
+ padding: 16px;
203
+ box-sizing: border-box;
204
+ }
205
+
206
+ h3 {
207
+ margin: 0;
208
+ max-width: 300px;
209
+ overflow: hidden;
210
+ text-overflow: ellipsis;
211
+ white-space: nowrap;
212
+ color: var(--re-text-color, #000) !important;
213
+ }
214
+ p {
215
+ margin: 10px 0 0 0;
216
+ max-width: 300px;
217
+ font-size: 14px;
218
+ line-height: 17px;
219
+ overflow: hidden;
220
+ text-overflow: ellipsis;
221
+ white-space: nowrap;
222
+ color: var(--re-text-color, #000) !important;
223
+ }
224
+
225
+ .value-container {
226
+ display: flex;
227
+ flex-wrap: wrap;
228
+ align-items: center;
229
+ justify-content: center;
230
+ flex: 1;
231
+ overflow: hidden;
232
+ position: relative;
233
+ gap: 12px;
234
+ }
235
+
236
+ .single-value {
237
+ overflow: hidden;
238
+ position: relative;
239
+ align-items: end;
240
+ font-size: 26px;
241
+ padding: 6px;
242
+ box-sizing: border-box;
243
+ /* border-left: 4px solid #ddd; */
244
+ }
245
+
246
+ .current-value {
247
+ font-size: 32px;
248
+ font-weight: 600;
249
+ white-space: nowrap;
250
+ color: var(--re-text-color, #000);
251
+ }
252
+
253
+ .label {
254
+ font-weight: 300;
255
+ font-size: 26px;
256
+ color: var(--re-text-color, #000);
257
+ white-space: nowrap;
258
+ }
259
+ `
260
+
261
+ render() {
262
+ return html`
263
+ <div class="wrapper">
264
+ <header>
265
+ <h3 class="paging" ?active=${this.inputData?.settings?.title}>
266
+ ${this.inputData?.settings?.title}
267
+ </h3>
268
+ <p class="paging" ?active=${this.inputData?.settings?.subTitle}>
269
+ ${this.inputData?.settings?.subTitle}
270
+ </p>
271
+ </header>
272
+ <div class="value-container">
273
+ ${repeat(
274
+ // @ts-ignore
275
+ this.dataSets,
276
+ ([label]) => label,
277
+ ([label, ds]) => {
278
+ return html`
279
+ <div class="single-value">
280
+ <div class="label paging" ?active=${this.textActive} label="${label}">
281
+ ${label}
282
+ </div>
283
+ <span
284
+ class="current-value paging"
285
+ ?active=${this.textActive}
286
+ label="${label}"
287
+ >
288
+ ${isNaN(ds.needleValue as number)
289
+ ? ''
290
+ : (ds.needleValue as number).toFixed(0)}
291
+ </span>
292
+ <span class="label paging" label="${label}" ?active=${this.textActive}>
293
+ ${ds.unit}
294
+ </span>
295
+ </div>
296
+ `
297
+ }
298
+ )}
299
+ </div>
300
+ </div>
301
+ `
233
302
  }
234
- `;
235
-
236
- render() {
237
- return html`
238
- <div class="wrapper">
239
- <header>
240
- <h3 class="paging" ?active=${this.inputData?.settings?.title}>${this.inputData?.settings?.title}</h3>
241
- <p class="paging" ?active=${this.inputData?.settings?.subTitle}>${this.inputData?.settings?.subTitle}</p>
242
- </header>
243
- <div class="value-container">
244
- ${repeat(// @ts-ignore
245
- this.dataSets, ([label]) => label, ([label, ds]) => {
246
- return html`
247
- <div class="single-value">
248
- <div
249
- class="label paging"
250
- ?active=${this.textActive}
251
- label="${label}"
252
- >
253
- ${label}
254
- </div>
255
- <span
256
- class="current-value paging"
257
- ?active=${this.textActive}
258
- label="${label}">
259
- ${isNaN(ds.needleValue) ? '' : ds.needleValue.toFixed(0)}
260
- </span>
261
- <span class="label paging" label="${label}" ?active=${this.textActive} >
262
- ${ds.unit}
263
- </span>
264
- </div>
265
- `})}
266
- </div>
267
- </div>
268
- `;
269
- }
270
303
  }
271
304
 
272
- window.customElements.define('widget-value-versionplaceholder', WidgetValue);
305
+ window.customElements.define('widget-value-versionplaceholder', WidgetValue)
@@ -1,28 +0,0 @@
1
- export interface Settings {
2
- title: string;
3
- subTitle: string;
4
- columnLayout: boolean;
5
- }
6
- export interface Data {
7
- value: number;
8
- pivot: string;
9
- }
10
- export interface Dataseries {
11
- label: string;
12
- order: number;
13
- unit: string;
14
- labelColor: string;
15
- valueColor: string;
16
- averageLatest: number;
17
- labelFontSize: number;
18
- valueFontSize: number;
19
- backgroundColor: string;
20
- data: Data[];
21
- needleValue: number;
22
- range: number;
23
- ranges: number[];
24
- }
25
- export interface InputData {
26
- settings: Settings;
27
- dataseries: Dataseries[];
28
- }