@operato/scene-chartjs 0.0.5

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.
Files changed (114) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +21 -0
  3. package/README.md +21 -0
  4. package/assets/bar-chart.png +0 -0
  5. package/assets/doughnut-chart.png +0 -0
  6. package/assets/horizontal-bar-chart.png +0 -0
  7. package/assets/line-chart.png +0 -0
  8. package/assets/mixed-chart.png +0 -0
  9. package/assets/pie-chart.png +0 -0
  10. package/assets/polar-area-chart.png +0 -0
  11. package/assets/radar-chart.png +0 -0
  12. package/demo/bar.html +266 -0
  13. package/demo/chartjs.html +73 -0
  14. package/demo/index.html +547 -0
  15. package/demo/legend.html +267 -0
  16. package/demo/things-scene-chartjs.html +7 -0
  17. package/dist/chartjs.d.ts +27 -0
  18. package/dist/chartjs.js +109 -0
  19. package/dist/chartjs.js.map +1 -0
  20. package/dist/config-converter.d.ts +1 -0
  21. package/dist/config-converter.js +343 -0
  22. package/dist/config-converter.js.map +1 -0
  23. package/dist/editors/index.d.ts +5 -0
  24. package/dist/editors/index.js +11 -0
  25. package/dist/editors/index.js.map +1 -0
  26. package/dist/editors/property-editor-chartjs-abstract.d.ts +44 -0
  27. package/dist/editors/property-editor-chartjs-abstract.js +250 -0
  28. package/dist/editors/property-editor-chartjs-abstract.js.map +1 -0
  29. package/dist/editors/property-editor-chartjs-hbar.d.ts +9 -0
  30. package/dist/editors/property-editor-chartjs-hbar.js +160 -0
  31. package/dist/editors/property-editor-chartjs-hbar.js.map +1 -0
  32. package/dist/editors/property-editor-chartjs-mixed.d.ts +20 -0
  33. package/dist/editors/property-editor-chartjs-mixed.js +193 -0
  34. package/dist/editors/property-editor-chartjs-mixed.js.map +1 -0
  35. package/dist/editors/property-editor-chartjs-multi-series-abstract.d.ts +31 -0
  36. package/dist/editors/property-editor-chartjs-multi-series-abstract.js +373 -0
  37. package/dist/editors/property-editor-chartjs-multi-series-abstract.js.map +1 -0
  38. package/dist/editors/property-editor-chartjs-pie.d.ts +14 -0
  39. package/dist/editors/property-editor-chartjs-pie.js +70 -0
  40. package/dist/editors/property-editor-chartjs-pie.js.map +1 -0
  41. package/dist/editors/property-editor-chartjs-radar.d.ts +10 -0
  42. package/dist/editors/property-editor-chartjs-radar.js +42 -0
  43. package/dist/editors/property-editor-chartjs-radar.js.map +1 -0
  44. package/dist/editors/property-editor-chartjs-styles.d.ts +1 -0
  45. package/dist/editors/property-editor-chartjs-styles.js +165 -0
  46. package/dist/editors/property-editor-chartjs-styles.js.map +1 -0
  47. package/dist/editors/property-editor-chartjs.d.ts +14 -0
  48. package/dist/editors/property-editor-chartjs.js +83 -0
  49. package/dist/editors/property-editor-chartjs.js.map +1 -0
  50. package/dist/index.d.ts +5 -0
  51. package/dist/index.js +8 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/ox-chart.d.ts +20 -0
  54. package/dist/ox-chart.js +137 -0
  55. package/dist/ox-chart.js.map +1 -0
  56. package/dist/plugins/chart-series-highlight.d.ts +5 -0
  57. package/dist/plugins/chart-series-highlight.js +37 -0
  58. package/dist/plugins/chart-series-highlight.js.map +1 -0
  59. package/dist/plugins/chartjs-plugin-data-binder.d.ts +5 -0
  60. package/dist/plugins/chartjs-plugin-data-binder.js +111 -0
  61. package/dist/plugins/chartjs-plugin-data-binder.js.map +1 -0
  62. package/helps/scene/component/chartjs.ko.md +332 -0
  63. package/helps/scene/component/chartjs.md +333 -0
  64. package/helps/scene/component/chartjs.zh.md +331 -0
  65. package/helps/scene/images/chart-bar-01.png +0 -0
  66. package/helps/scene/images/chart-bar-02.png +0 -0
  67. package/helps/scene/images/chart-bar-03.png +0 -0
  68. package/helps/scene/images/chart-bar-08.png +0 -0
  69. package/helps/scene/images/chart-bar-12.png +0 -0
  70. package/helps/scene/images/chart-data-01.png +0 -0
  71. package/helps/scene/images/chart-data-04.png +0 -0
  72. package/helps/scene/images/chart-doughnut-01.png +0 -0
  73. package/helps/scene/images/chart-horizontal-bar-01.png +0 -0
  74. package/helps/scene/images/chart-line-01.png +0 -0
  75. package/helps/scene/images/chart-mix-01.png +0 -0
  76. package/helps/scene/images/chart-mix-02.png +0 -0
  77. package/helps/scene/images/chart-pie-01.png +0 -0
  78. package/helps/scene/images/chart-polar-01.png +0 -0
  79. package/helps/scene/images/chart-radar-01.png +0 -0
  80. package/package.json +78 -0
  81. package/src/chartjs.ts +134 -0
  82. package/src/config-converter.ts +401 -0
  83. package/src/editors/index.ts +11 -0
  84. package/src/editors/property-editor-chartjs-abstract.ts +301 -0
  85. package/src/editors/property-editor-chartjs-hbar.ts +163 -0
  86. package/src/editors/property-editor-chartjs-mixed.ts +204 -0
  87. package/src/editors/property-editor-chartjs-multi-series-abstract.ts +393 -0
  88. package/src/editors/property-editor-chartjs-pie.ts +79 -0
  89. package/src/editors/property-editor-chartjs-radar.ts +43 -0
  90. package/src/editors/property-editor-chartjs-styles.ts +165 -0
  91. package/src/editors/property-editor-chartjs.ts +88 -0
  92. package/src/index.ts +7 -0
  93. package/src/ox-chart.ts +150 -0
  94. package/src/plugins/chart-series-highlight.ts +43 -0
  95. package/src/plugins/chartjs-plugin-data-binder.ts +138 -0
  96. package/src/scene-chart.d.ts +152 -0
  97. package/templates/bar-chart.js +124 -0
  98. package/templates/doughnut-chart.js +58 -0
  99. package/templates/horizontal-bar-chart.js +121 -0
  100. package/templates/index.js +22 -0
  101. package/templates/line-chart.js +155 -0
  102. package/templates/mixed-chart.js +152 -0
  103. package/templates/pie-chart.js +58 -0
  104. package/templates/polar-area-chart.js +92 -0
  105. package/templates/radar-chart.js +98 -0
  106. package/test/basic-test.html +61 -0
  107. package/test/index.html +20 -0
  108. package/things-scene.config.js +7 -0
  109. package/translations/en.json +5 -0
  110. package/translations/ko.json +5 -0
  111. package/translations/ms.json +5 -0
  112. package/translations/zh.json +5 -0
  113. package/tsconfig.json +22 -0
  114. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,401 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { TinyColor } from '@ctrl/tinycolor'
6
+
7
+ export function convertConfigure(chart: SceneChart.ChartConfig) {
8
+ if (!chart) return
9
+
10
+ var data = chart.data || {}
11
+ var datasets = data.datasets || []
12
+ var options = chart.options || {}
13
+ var scales = options.scales || {}
14
+ var xAxes: Array<SceneChart.ChartXAxe>
15
+ var yAxes: Array<SceneChart.ChartYAxe>
16
+ var scale
17
+ var legend = options.legend || {}
18
+ var tooltips = (options.tooltips = options.tooltips || {})
19
+
20
+ var multiAxis = options.multiAxis
21
+ var stacked = false
22
+ var yStacked = [false, false]
23
+ var fontSize = Number(options.defaultFontSize)
24
+ var fontFamily = options.defaultFontFamily
25
+ var fontColor = options.defaultFontColor
26
+ var theme = options.theme
27
+
28
+ // backward compatible
29
+ _configureBackwardsCompatible(chart.type, options)
30
+
31
+ // setup series configure
32
+ for (let i in datasets) {
33
+ let series = datasets[i]
34
+
35
+ if (options.stacked && !series.stack) {
36
+ series.stack = 'A'
37
+ }
38
+
39
+ /*
40
+ * TODO from chartjs 2.9, categoryPercentage, barPercentage properties move to dataset.
41
+ * so need to move related properties - categorySpacing, barSpacing should be moved to series.
42
+ */
43
+ if (chart.type == 'bar') {
44
+ let categorySpacing = (scales.xAxes && scales.xAxes[0].categorySpacing) || 0
45
+ let barSpacing = (scales.xAxes && scales.xAxes[0].barSpacing) || 0
46
+
47
+ series.categoryPercentage = 1 - categorySpacing || 1
48
+ series.barPercentage = 1 - barSpacing || 0.8
49
+ } else if (chart.type == 'horizontalBar') {
50
+ let categorySpacing = (scales.yAxes && scales.yAxes[0].categorySpacing) || 0
51
+ let barSpacing = (scales.yAxes && scales.yAxes[0].barSpacing) || 0
52
+
53
+ series.categoryPercentage = 1 - categorySpacing || 1
54
+ series.barPercentage = 1 - barSpacing || 0.8
55
+ }
56
+
57
+ _setSeriesConfigures(series, chart)
58
+
59
+ if (!multiAxis) {
60
+ if (series.yAxisID == 'right') series.yAxisID = 'left'
61
+ }
62
+ }
63
+
64
+ delete options.stacked
65
+
66
+ var leftSeries = datasets.filter(d => d.yAxisID == 'left')
67
+ var rightSeries = datasets.filter(d => d.yAxisID == 'right')
68
+
69
+ leftSeries.forEach(s => {
70
+ var filtered = leftSeries.filter(ss => s.stack == ss.stack)
71
+ if (filtered.length > 1) {
72
+ yStacked[0] = true
73
+ return
74
+ }
75
+ })
76
+
77
+ rightSeries.forEach(s => {
78
+ var filtered = rightSeries.filter(ss => s.stack == ss.stack)
79
+ if (filtered.length > 1) {
80
+ yStacked[1] = true
81
+ return
82
+ }
83
+ })
84
+
85
+ stacked = yStacked[0] || yStacked[1]
86
+
87
+ // setup options
88
+ // 1. setup scales
89
+ switch (chart.type) {
90
+ case 'line':
91
+ case 'bar':
92
+ case 'horizontalBar':
93
+ xAxes = scales.xAxes || []
94
+ yAxes = scales.yAxes || []
95
+
96
+ if (chart.type == 'horizontalBar') {
97
+ xAxes = scales.yAxes || []
98
+ yAxes = scales.xAxes || []
99
+ }
100
+
101
+ // 1-1. setup xAxes
102
+ for (let i in xAxes) {
103
+ let axis = xAxes[i]
104
+ _setStacked(axis, stacked)
105
+ _setScalesFont(axis, {
106
+ fontSize,
107
+ fontFamily
108
+ })
109
+ _setScalesAutoMinMax(axis)
110
+ _setScalesTickRotation(axis)
111
+ _setAxisTitle(axis)
112
+ _setScalesTheme(axis, theme, fontColor)
113
+ _appendTickCallback(axis.ticks)
114
+
115
+ axis.gridLines!.display = options.xGridLine
116
+ }
117
+
118
+ // 1-2. setup yAxes
119
+ for (let i in yAxes) {
120
+ let axis = yAxes[i]
121
+
122
+ //@ts-ignore
123
+ if (i == 1) {
124
+ _setMultiAxis(axis, multiAxis)
125
+ }
126
+ _setStacked(axis, yStacked[i])
127
+ _setScalesFont(axis, {
128
+ fontSize,
129
+ fontFamily
130
+ })
131
+ _setScalesAutoMinMax(axis)
132
+ _setAxisTitle(axis)
133
+ _setScalesTheme(axis, theme, fontColor)
134
+ _appendTickCallback(axis.ticks)
135
+
136
+ //@ts-ignore
137
+ if (i == 0) axis.gridLines.display = options.yGridLine
138
+
139
+ //@ts-ignore
140
+ if (i == 1) axis.gridLines.display = options.y2ndGridLine
141
+ }
142
+
143
+ break
144
+ case 'pie':
145
+ case 'doughnut':
146
+ break
147
+ default:
148
+ scale = options.scale || {}
149
+ _setScalesFont(scale, {
150
+ fontSize,
151
+ fontFamily
152
+ })
153
+ break
154
+ }
155
+
156
+ // 2. setup legend
157
+ _setLegendFont(legend, {
158
+ fontSize,
159
+ fontFamily
160
+ })
161
+ legend.labels && (legend.labels.boxWidth = 15)
162
+ _setLegendTheme(legend, theme, fontColor)
163
+
164
+ // 3. setup tooltips
165
+ _setTooltipFont(tooltips, {
166
+ fontSize,
167
+ fontFamily
168
+ })
169
+ _setTooltipCallback(tooltips)
170
+ }
171
+
172
+ function _configureBackwardsCompatible(type: string, options: SceneChart.ChartOptions) {
173
+ switch (type) {
174
+ case 'horizontalBar':
175
+ if (!options.scales) options.scales = {}
176
+ break
177
+ case 'radar':
178
+ case 'polarArea':
179
+ if (options.defaultFontColor) {
180
+ options.scale!.ticks!.fontColor = options.defaultFontColor
181
+ if (options.scale.pointLabels) {
182
+ options.scale.pointLabels.fontColor = options.defaultFontColor
183
+ } else {
184
+ options.scale.pointLabels = { fontColor: options.defaultFontColor }
185
+ }
186
+ }
187
+ options.scale!.ticks!.backdropColor = options.fillStyle ? options.fillStyle : '#00ff0000'
188
+ break
189
+ case 'line':
190
+ case 'bar':
191
+ if (!options.scales) options.scales = {}
192
+ if (!options.scales.yAxes) options.scales.yAxes = []
193
+
194
+ if (options.scales.yAxes.length === 1) {
195
+ let yAxes = options.scales.yAxes
196
+ yAxes.push({
197
+ position: 'right',
198
+ id: 'right',
199
+ display: options.multiAxis || false,
200
+ gridLines: {
201
+ display: (yAxes[0] && yAxes[0].gridLines && yAxes[0].gridLines.display) || false
202
+ },
203
+ ticks: {
204
+ beginAtZero: false,
205
+ callback: function (value: any, index: number, values: any[]) {
206
+ var returnValue = value
207
+ if (typeof returnValue == 'number') {
208
+ returnValue = returnValue.toLocaleString()
209
+ }
210
+
211
+ return returnValue
212
+ }
213
+ }
214
+ })
215
+ }
216
+ break
217
+ case 'pie':
218
+ case 'doughnut':
219
+ break
220
+ default:
221
+ if (!options.scale) options.scale = {}
222
+
223
+ break
224
+ }
225
+ }
226
+
227
+ function _setStacked(axis: SceneChart.ChartXAxe, stacked: boolean) {
228
+ axis.stacked = stacked
229
+ }
230
+
231
+ function _setMultiAxis(axis: SceneChart.ChartXAxe, multiAxis: boolean) {
232
+ axis.display = multiAxis
233
+ }
234
+
235
+ function _setAxisTitle(axis: SceneChart.ChartXAxe) {
236
+ if (!axis.scaleLabel) axis.scaleLabel = {}
237
+ axis.scaleLabel.labelString = axis.axisTitle
238
+ axis.scaleLabel.display = axis.axisTitle ? true : false
239
+ }
240
+
241
+ function _setScalesFont(
242
+ axis: SceneChart.ChartXAxe | SceneChart.RadialLinearScale,
243
+ { fontSize, fontFamily }: { fontSize: number; fontFamily: string }
244
+ ) {
245
+ axis.ticks = axis.ticks ? axis.ticks : {}
246
+ axis.ticks.fontSize = fontSize
247
+
248
+ if (fontFamily) {
249
+ axis.ticks.fontFamily = fontFamily
250
+ }
251
+
252
+ ;(axis as SceneChart.RadialLinearScale).pointLabels = {
253
+ fontSize,
254
+ fontFamily
255
+ }
256
+ }
257
+
258
+ function _setScalesAutoMinMax(axis: SceneChart.ChartXAxe) {
259
+ axis.ticks = axis.ticks ? axis.ticks : {}
260
+
261
+ let autoMin = axis.ticks.autoMin
262
+ let autoMax = axis.ticks.autoMax
263
+
264
+ if (autoMin === true) {
265
+ delete axis.ticks.min
266
+ }
267
+ if (autoMax === true) {
268
+ delete axis.ticks.max
269
+ }
270
+ }
271
+
272
+ function _setScalesTickRotation(axis: SceneChart.ChartXAxe) {
273
+ axis.ticks = axis.ticks ? axis.ticks : {}
274
+ // axis.ticks.maxRotation = 0
275
+ }
276
+
277
+ function _setScalesTheme(axis: SceneChart.ChartXAxe, theme: SceneChart.Theme, fontColor: string) {
278
+ var baseColor = _getBaseColorFromTheme(theme)
279
+
280
+ axis.gridLines = axis.gridLines ? axis.gridLines : {}
281
+ if (axis.gridLines) {
282
+ axis.gridLines.zeroLineColor = baseColor.clone().setAlpha(0.5).toString()
283
+ axis.gridLines.color = baseColor.clone().setAlpha(0.1).toString()
284
+ }
285
+
286
+ axis.ticks = axis.ticks ? axis.ticks : {}
287
+ axis.ticks.fontColor = fontColor ? fontColor : baseColor.clone().setAlpha(0.5).toString()
288
+ }
289
+
290
+ function _setLegendFont(
291
+ legend: SceneChart.ChartLegendOptions,
292
+ { fontFamily, fontSize }: { fontFamily: string; fontSize: number }
293
+ ) {
294
+ legend.labels = legend.labels ? legend.labels : {}
295
+ legend.labels.fontSize = fontSize
296
+ if (fontFamily) legend.labels.fontFamily = fontFamily
297
+ }
298
+
299
+ function _setLegendTheme(legend: SceneChart.ChartLegendOptions, theme: SceneChart.Theme, fontColor: string) {
300
+ var baseColor = _getBaseColorFromTheme(theme)
301
+
302
+ legend.labels = legend.labels ? legend.labels : {}
303
+ legend.labels.fontColor = fontColor ? fontColor : baseColor.clone().setAlpha(0.5).toString()
304
+ }
305
+
306
+ function _getBaseColorFromTheme(theme: SceneChart.Theme) {
307
+ let darkColor = '#000'
308
+ let lightColor = '#fff'
309
+
310
+ var baseColor
311
+
312
+ switch (theme) {
313
+ case 'light':
314
+ baseColor = lightColor
315
+ break
316
+ case 'dark':
317
+ default:
318
+ baseColor = darkColor
319
+ break
320
+ }
321
+
322
+ baseColor = new TinyColor(baseColor)
323
+
324
+ return baseColor
325
+ }
326
+
327
+ function _setSeriesConfigures(series: SceneChart.ChartDataSets, chart: SceneChart.ChartConfig) {
328
+ var type = series.type || chart.type
329
+ var stackGroup = `${type} ${series.yAxisID} ${series.stack || series.dataKey}`
330
+ var color = series.color ? series.color : series.backgroundColor
331
+
332
+ switch (type) {
333
+ case 'bar':
334
+ case 'horizontalBar':
335
+ series.borderColor = series.backgroundColor = color
336
+ break
337
+
338
+ case 'line':
339
+ case 'radar':
340
+ color = series.color ? series.color : series.borderColor
341
+ series.pointBackgroundColor = series.pointBorderColor = series.borderColor = series.backgroundColor = color
342
+ series.pointBorderWidth = (series.borderWidth as number) * 0.5
343
+ series.pointHoverRadius = series.pointRadius
344
+ if (series.fill == undefined) series.fill = false
345
+ break
346
+
347
+ default:
348
+ series.borderColor = series.backgroundColor = color
349
+ break
350
+ }
351
+
352
+ series.stack = stackGroup
353
+ }
354
+
355
+ function _appendTickCallback(ticks: SceneChart.TickOptions | undefined) {
356
+ if (!ticks) {
357
+ return
358
+ }
359
+
360
+ ticks.callback = function (value, index, values) {
361
+ var returnValue
362
+ if (!Number.isNaN(Number(value))) {
363
+ returnValue = Number(value).toLocaleString()
364
+ } else {
365
+ returnValue = value
366
+ }
367
+
368
+ if (returnValue) return returnValue
369
+ }
370
+ }
371
+
372
+ function _setTooltipFont(
373
+ tooltips: SceneChart.ChartTooltipOptions,
374
+ { fontSize, fontFamily }: { fontSize: number; fontFamily: string }
375
+ ) {
376
+ tooltips.titleFontSize = tooltips.bodyFontSize = tooltips.footerFontSize = fontSize
377
+ if (fontFamily) tooltips.titleFontFamily = tooltips.bodyFontFamily = tooltips.footerFontFamily = fontFamily
378
+ }
379
+
380
+ function _setTooltipCallback(tooltips: SceneChart.ChartTooltipOptions) {
381
+ tooltips.callbacks = tooltips.callbacks || {}
382
+
383
+ tooltips.intersect = false
384
+ tooltips.mode = 'index'
385
+
386
+ tooltips.callbacks.label = function (tooltipItem: SceneChart.ChartTooltipItem, data: SceneChart.ChartData) {
387
+ var value = data.datasets?.[tooltipItem.datasetIndex || 0].data?.[tooltipItem.index || 0]
388
+ var datasetLabel = data.datasets?.[tooltipItem.datasetIndex || 0].label
389
+ var label = datasetLabel || data.labels?.[tooltipItem.index || 0]
390
+ var toNumValue = Number(value)
391
+
392
+ if (!isNaN(toNumValue)) {
393
+ value = toNumValue
394
+ }
395
+
396
+ var prefix = data.datasets?.[tooltipItem.datasetIndex || 0].valuePrefix || ''
397
+ var suffix = data.datasets?.[tooltipItem.datasetIndex || 0].valueSuffix || ''
398
+
399
+ return `${label}: ${prefix + value?.toLocaleString() + suffix}`
400
+ }
401
+ }
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import ChartJSEditor from './property-editor-chartjs'
5
+
6
+ export default [
7
+ {
8
+ type: 'chartjs',
9
+ element: ChartJSEditor.is
10
+ }
11
+ ]
@@ -0,0 +1,301 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { html, LitElement } from 'lit'
6
+ import { property } from 'lit/decorators.js'
7
+
8
+ import { random as randomColor, TinyColor } from '@ctrl/tinycolor'
9
+
10
+ import { PropertyEditorChartJSStyles } from './property-editor-chartjs-styles'
11
+
12
+ export default class PropertyEditorChartJSAbstract extends LitElement {
13
+ static styles = [PropertyEditorChartJSStyles]
14
+
15
+ @property({ type: Object }) value: any = {}
16
+ @property({ type: Number }) currentSeriesIndex: number = 0
17
+
18
+ render() {
19
+ return html`
20
+ <legend><i18n-msg msgid="label.chart">Chart</i18n-msg></legend>
21
+
22
+ <label> <i18n-msg msgid="label.theme">theme</i18n-msg> </label>
23
+ <select value-key="theme" class="select-content" .value=${this.theme}>
24
+ <option value="dark">dark</option>
25
+ <option value="light">light</option>
26
+ </select>
27
+
28
+ <input type="checkbox" value-key="display" .checked=${this.display} />
29
+ <label> <i18n-msg msgid="label.legend">Legend</i18n-msg> </label>
30
+
31
+ ${this.display
32
+ ? html`
33
+ <label> <i18n-msg msgid="label.position">Position</i18n-msg> </label>
34
+ <select value-key="position" class="select-content" .value=${this.position}>
35
+ <option value="top">top</option>
36
+ <option value="right">right</option>
37
+ <option value="bottom">bottom</option>
38
+ <option value="left">left</option>
39
+ </select>
40
+ `
41
+ : html``}
42
+ ${this.editorTemplate(this)}
43
+ `
44
+ }
45
+
46
+ firstUpdated() {
47
+ this.renderRoot.addEventListener('change', this.onValuesChanged.bind(this))
48
+ }
49
+
50
+ displayValueTemplate() {
51
+ return html`
52
+ <label> <i18n-msg msgid="label.value-prefix">Value Prefix</i18n-msg> </label>
53
+ <input type="text" value-key="series.valuePrefix" .value=${this.series.valuePrefix || ''} />
54
+
55
+ <label> <i18n-msg msgid="label.value-suffix">Value suffix</i18n-msg> </label>
56
+ <input type="text" value-key="series.valueSuffix" .value=${this.series.valueSuffix || ''} />
57
+
58
+ <input type="checkbox" value-key="series.displayValue" .checked=${this.series.displayValue || false} />
59
+ <label> <i18n-msg msgid="label.value-display">Value Display</i18n-msg> </label>
60
+
61
+ ${this.series.displayValue
62
+ ? html`
63
+ <label> <i18n-msg msgid="label.font-color">Font Color</i18n-msg> </label>
64
+ <things-editor-color
65
+ value-key="series.defaultFontColor"
66
+ .value=${this.series.defaultFontColor || '#000'}
67
+ ></things-editor-color>
68
+ <label> <i18n-msg msgid="label.font-size">Font Size</i18n-msg> </label>
69
+ <input type="number" value-key="series.defaultFontSize" .value=${this.series.defaultFontSize || 10} />
70
+ <label> <i18n-msg msgid="label.position">Position</i18n-msg> </label>
71
+ <select value-key="series.dataLabelAnchor" .value=${this.series.dataLabelAnchor || 'center'}>
72
+ <option value="start">Start</option>
73
+ <option value="center" selected>Center</option>
74
+ <option value="end">End</option>
75
+ </select>
76
+ `
77
+ : html``}
78
+ `
79
+ }
80
+
81
+ editorTemplate(props: any) {
82
+ return html``
83
+ }
84
+
85
+ get data() {
86
+ return this.value.data
87
+ }
88
+
89
+ set data(data) {
90
+ this.value.data = data
91
+ }
92
+
93
+ get datasets() {
94
+ if (!this.data.datasets) this.data.datasets = []
95
+
96
+ return this.data.datasets
97
+ }
98
+
99
+ set datasets(datasets) {
100
+ this.datasets = datasets
101
+ }
102
+
103
+ get series() {
104
+ if (!this.datasets[this.currentSeriesIndex]) this.datasets[this.currentSeriesIndex] = {}
105
+ return this.datasets[this.currentSeriesIndex]
106
+ }
107
+
108
+ set series(series) {
109
+ !this.data ? (this.data = { dataset: [series] }) : (this.datasets[this.currentSeriesIndex] = series)
110
+ }
111
+
112
+ set dataKey(key) {
113
+ this.series.dataKey = key
114
+ }
115
+
116
+ get dataKey() {
117
+ return this.series.dataKey
118
+ }
119
+
120
+ get legend() {
121
+ !this.value.options && (this.value.options = {})
122
+ return this.value.options.legend
123
+ }
124
+
125
+ set legend(legend) {
126
+ this.value.options.legend = legend
127
+ }
128
+
129
+ get theme() {
130
+ return this.value.options && this.value.options.theme
131
+ }
132
+
133
+ set theme(theme) {
134
+ !this.value.options && (this.value.options = {})
135
+ this.value.options.theme = theme
136
+ }
137
+
138
+ get scales() {
139
+ return this.value.options.scales
140
+ }
141
+
142
+ set scales(scales) {
143
+ !this.value.options && (this.value.options = {})
144
+ this.value.options.scales = scales
145
+ }
146
+
147
+ get display() {
148
+ return this.legend && this.legend.display
149
+ }
150
+
151
+ set display(display) {
152
+ this.legend.display = display
153
+ }
154
+
155
+ get position() {
156
+ return this.legend.position
157
+ }
158
+
159
+ set position(position) {
160
+ this.legend.position = position
161
+ }
162
+
163
+ get stacked() {
164
+ return this.value.options.stacked
165
+ }
166
+
167
+ set stacked(stacked) {
168
+ this.value.options.stacked = stacked
169
+ }
170
+
171
+ get labelDataKey() {
172
+ return this.data && this.data.labelDataKey
173
+ }
174
+
175
+ set labelDataKey(labelDataKey) {
176
+ this.data.labelDataKey = labelDataKey
177
+ }
178
+
179
+ set options(options) {
180
+ this.value.options = options
181
+ }
182
+
183
+ get options() {
184
+ return this.value.options
185
+ }
186
+
187
+ onValuesChanged(e: Event) {
188
+ var element = e.target as HTMLInputElement
189
+ var key = element.getAttribute('value-key')
190
+ var value = element.value
191
+
192
+ if (!key) {
193
+ return
194
+ }
195
+
196
+ value = this._getElementValue(element)
197
+
198
+ var attrs = key.split('.')
199
+ var attr = attrs.shift() || ''
200
+ var variable = this
201
+
202
+ while (attrs.length > 0) {
203
+ //@ts-ignore
204
+ variable = variable[attr]
205
+ attr = attrs.shift() || ''
206
+ }
207
+
208
+ //@ts-ignore
209
+ variable[attr] = value
210
+
211
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
212
+ this.requestUpdate()
213
+ }
214
+
215
+ onTapAddTab(e: Event) {
216
+ if (!this.value.data.datasets) return
217
+
218
+ var lastSeriesIndex = this.value.data.datasets.length
219
+ var chartType = this.series.type || this.value.type
220
+ var lastSeriesColor = new TinyColor(this.datasets[lastSeriesIndex - 1].backgroundColor)
221
+
222
+ var seriesModel = this._getSeriesModel({
223
+ chartType,
224
+ datasetsLength: lastSeriesIndex,
225
+ lastSeriesColor
226
+ })
227
+
228
+ this.value.data.datasets.push(seriesModel)
229
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
230
+ this.currentSeriesIndex = lastSeriesIndex
231
+ }
232
+
233
+ onTapRemoveCurrentTab(e: Event) {
234
+ if (!this.value.data.datasets) return
235
+
236
+ var currIndex = this.currentSeriesIndex
237
+ this.value.data.datasets.splice(currIndex, 1)
238
+
239
+ currIndex--
240
+
241
+ if (currIndex < 0) currIndex = 0
242
+
243
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
244
+ this.currentSeriesIndex = currIndex
245
+
246
+ this.requestUpdate()
247
+ }
248
+
249
+ _getSeriesModel({
250
+ chartType,
251
+ datasetsLength,
252
+ lastSeriesColor
253
+ }: {
254
+ chartType: any
255
+ datasetsLength: number
256
+ lastSeriesColor: TinyColor
257
+ }) {
258
+ var addSeriesOption: any = {
259
+ label: `series ${datasetsLength + 1}`,
260
+ data: [],
261
+ borderWidth: 1,
262
+ dataKey: '',
263
+ yAxisID: 'left',
264
+ color: randomColor({
265
+ hue: lastSeriesColor as any
266
+ }).toRgbString()
267
+ }
268
+
269
+ addSeriesOption.type = addSeriesOption.chartType = chartType
270
+ return addSeriesOption
271
+ }
272
+
273
+ _getElementValue(element: HTMLElement) {
274
+ switch (element.tagName) {
275
+ case 'INPUT':
276
+ switch ((element as HTMLInputElement).type) {
277
+ case 'checkbox':
278
+ return (element as HTMLInputElement).checked
279
+ case 'number':
280
+ return Number((element as HTMLInputElement).value) || 0
281
+ case 'text':
282
+ return String((element as HTMLInputElement).value)
283
+ }
284
+
285
+ case 'PAPER-BUTTON':
286
+ return (element as any).active
287
+
288
+ case 'PAPER-LISTBOX':
289
+ return (element as any).selected
290
+
291
+ case 'THINGS-EDITOR-MULTIPLE-COLOR':
292
+ return (element as any).values
293
+
294
+ case 'THINGS-EDITOR-ANGLE-INPUT':
295
+ return Number((element as any).radian) || 0
296
+
297
+ default:
298
+ return (element as any).value
299
+ }
300
+ }
301
+ }