@operato/scene-chartjs 8.0.0-beta.1 → 8.0.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/src/ox-chart.ts DELETED
@@ -1,170 +0,0 @@
1
- import 'chartjs-plugin-datalabels'
2
- import 'chartjs-plugin-style'
3
-
4
- import { LitElement, PropertyValues, html } from 'lit'
5
- import { customElement, property, query } from 'lit/decorators.js'
6
-
7
- import { Chart } from 'chart.js'
8
- import { format as formatText } from '@operato/utils/format.js'
9
- import DataBinderPlugin from './plugins/chartjs-plugin-data-binder'
10
- import { convertConfigure } from './config-converter'
11
-
12
- Chart.plugins.register(DataBinderPlugin)
13
-
14
- @customElement('ox-chart')
15
- export class OxChart extends LitElement {
16
- @property({ type: Number }) width!: number
17
- @property({ type: Number }) height!: number
18
- @property({ type: Object }) options!: SceneChart.ChartConfig
19
- @property({ type: Object }) data!: SceneChart.ChartData
20
-
21
- private _chart?: SceneChart | null
22
-
23
- @query('canvas') _canvas!: HTMLCanvasElement
24
-
25
- firstUpdated() {
26
- this.initChart()
27
- }
28
-
29
- render() {
30
- return html` <canvas></canvas> `
31
- }
32
-
33
- dispose() {
34
- this._chart?.destroy()
35
- this._chart = null
36
- }
37
-
38
- updated(changes: PropertyValues<this>) {
39
- if (changes.has('width') || changes.has('height')) {
40
- this.updateChartSize()
41
- }
42
-
43
- if (changes.has('options')) {
44
- this.updateChartConfig()
45
- }
46
-
47
- if (changes.has('data')) {
48
- this._chart!.data.rawData = this.data
49
- this._chart!.update()
50
- }
51
- }
52
-
53
- initChart() {
54
- const { data, options, type } = this.options
55
- this.options.options.tooltip = this.options.options.tooltip ?? true
56
- options!.maintainAspectRatio = false
57
-
58
- this.attachPluginOptions(options)
59
- convertConfigure(this.options as SceneChart.ChartConfig)
60
-
61
- this._chart = new Chart(this._canvas, {
62
- type,
63
- data,
64
- options
65
- }) as SceneChart
66
-
67
- this.updateChartSize()
68
- }
69
-
70
- updateChartSize() {
71
- const width = Math.floor(this.width)
72
- const height = Math.floor(this.height)
73
-
74
- this._canvas.style.width = `${width}px`
75
- this._canvas.style.height = `${height}px`
76
-
77
- const _ = () => {
78
- if (this._canvas.offsetWidth == 0 || this._canvas.offsetHeight == 0) {
79
- requestAnimationFrame(_)
80
- } else {
81
- /*
82
- 주의 : chart.resize() 내에서 pixel ratio를 감안해서, canvas 의 width, height를 설정하기때문에,
83
- 별도 처리가 필요하지 않다.
84
- */
85
- this._chart!.resize()
86
- }
87
- }
88
-
89
- requestAnimationFrame(_)
90
- }
91
-
92
- updateChartConfig() {
93
- if (!this._chart) return
94
-
95
- const { data, options, type } = this.options
96
- options!.maintainAspectRatio = false
97
-
98
- this.attachPluginOptions(options)
99
- convertConfigure(this.options as SceneChart.ChartConfig)
100
-
101
- this._chart.type = type
102
- this._chart.data = data
103
- this._chart.options = options
104
- this._chart.data.rawData = this.data
105
- this._chart.update()
106
- }
107
-
108
- attachPluginOptions(options: SceneChart.ChartOptions) {
109
- if (!options.plugins) {
110
- options.plugins = {}
111
- }
112
-
113
- this.attachDatalabelPluginOptions(options.plugins)
114
- }
115
-
116
- attachDatalabelPluginOptions(pluginOptions: SceneChart.ChartPluginsOptions) {
117
- pluginOptions.datalabels = {
118
- ...pluginOptions.datalabels,
119
- display: function (context) {
120
- // 기존 boolean type 을 string으로 바꾸면서 T, F, auto 추가 (실제 타입은 true, false, 'auto')
121
- //@ts-ignore
122
- const displayValue = context.dataset.displayValue || false
123
- return displayValue === 'T' ? true : displayValue === 'F' ? false : displayValue
124
- },
125
- anchor: function (context) {
126
- //@ts-ignore
127
- return context.dataset.dataLabelAnchor || 'center'
128
- },
129
- offset: function (context) {
130
- //@ts-ignore
131
- return context.dataset.dataLabelOffset || 0
132
- },
133
- //@ts-ignore
134
- align: function (context) {
135
- //@ts-ignore
136
- return context.dataset.dataLabelAnchor || 'center'
137
- },
138
- //@ts-ignore
139
- rotation: function (context) {
140
- //@ts-ignore
141
- return context.dataset.dataLabelRotation || 0
142
- },
143
- color: function (context) {
144
- //@ts-ignore
145
- return context.dataset?.defaultFontColor || '#000'
146
- },
147
- font: function (context) {
148
- return {
149
- //@ts-ignore
150
- size: context.dataset?.defaultFontSize,
151
- //@ts-ignore
152
- family: context.chart.options?.defaultFontFamily
153
- }
154
- },
155
- clamp: true,
156
- formatter: function (value, context) {
157
- //@ts-ignore
158
- var format = context.dataset.valueFormat || ''
159
- //@ts-ignore
160
- var prefix = context.dataset.valuePrefix || ''
161
- //@ts-ignore
162
- var suffix = context.dataset.valueSuffix || ''
163
- if (value == undefined) return value
164
-
165
- var stringValue = format ? formatText(format, Number(value)) : Number(value).toLocaleString()
166
- return prefix + stringValue + suffix
167
- }
168
- }
169
- }
170
- }
@@ -1,41 +0,0 @@
1
- import 'ses'
2
-
3
- function seriesHighlight(chartInstance: SceneChart, seriesData: SceneChart.DataSeries) {
4
- chartInstance.data.datasets?.forEach(dataset => {
5
- let highlight = dataset.highlight
6
- if (!highlight) {
7
- return
8
- }
9
-
10
- let highlightColor = highlight.color
11
- let highlightCondition = highlight.condition
12
- const c = new Compartment()
13
-
14
- seriesData.forEach((sdata, sIndex) => {
15
- sdata.forEach((data: SceneChart.Data, i: number) => {
16
- if (!c.evaluate(highlightCondition)) {
17
- return
18
- }
19
-
20
- let meta = chartInstance.getDatasetMeta(sIndex)
21
- meta.data[i]._model.backgroundColor = highlightColor
22
- //@ts-ignore
23
- meta.data[i]._model.hoverBackgroundColor = highlightColor
24
-
25
- // dataset.backgroundColor = highlightColor
26
- })
27
- })
28
- })
29
- }
30
-
31
- export default {
32
- id: 'chart-series-highlight',
33
- beforeDraw: function (chartInstance: SceneChart) {
34
- if (!chartInstance.data.rawData) {
35
- return
36
- }
37
-
38
- let seriesData = chartInstance.data.rawData.seriesData
39
- seriesHighlight(chartInstance, seriesData)
40
- }
41
- }
@@ -1,134 +0,0 @@
1
- function convertObject(
2
- dataArray: string | SceneChart.DataSeries | Object,
3
- chartInstance: SceneChart
4
- ): null | Object | SceneChart.DataSeries {
5
- if (!dataArray) {
6
- return null
7
- }
8
-
9
- if (typeof dataArray == 'string') {
10
- try {
11
- dataArray = JSON.parse(dataArray)
12
- } catch (e) {
13
- console.warn('invalid chart data format', e)
14
- return null
15
- }
16
- }
17
-
18
- if (!(dataArray instanceof Array)) {
19
- // is not Array
20
- if (dataArray instanceof Object) {
21
- return dataArray
22
- }
23
- return null
24
- }
25
-
26
- if (dataArray.length === 0) {
27
- return null
28
- }
29
-
30
- // modeling중 변수 기본값에 대한 처리
31
- if (dataArray[0].hasOwnProperty('__field1')) {
32
- dataArray = toObjectArrayValue(dataArray) as SceneChart.DataSeries
33
- }
34
-
35
- let label = chartInstance.data.labelDataKey
36
- let seriesKeys = []
37
-
38
- for (let i in chartInstance.data.datasets) {
39
- seriesKeys.push(chartInstance.data.datasets[Number(i)].dataKey)
40
- }
41
-
42
- let seriesData: SceneChart.DataSeries = []
43
- let labelData: SceneChart.DataSeries = []
44
-
45
- let convertedObject = {
46
- seriesData,
47
- labelData
48
- }
49
-
50
- for (let i = 0; i < (dataArray as Array<any>).length; i++) {
51
- let currData: SceneChart.Data = (dataArray as SceneChart.DataSeries)[Number(i)]
52
- labelData.push(currData[label!])
53
-
54
- for (let i in seriesKeys) {
55
- if (!seriesKeys[i]) continue
56
-
57
- if (!seriesData[i]) seriesData[i] = []
58
-
59
- // 값이 NaN 경우엔 차트를 그리지 않음
60
- if (isNaN(currData[seriesKeys[i]])) {
61
- currData[seriesKeys[i]] = NaN
62
- }
63
-
64
- seriesData[i].push(currData[seriesKeys[i]])
65
- }
66
- }
67
-
68
- return convertedObject
69
- }
70
-
71
- function toObjectArrayValue(array: SceneChart.DataSeries): SceneChart.DataSeries | null {
72
- if (!array || array.length === 0) {
73
- return null
74
- }
75
-
76
- let indexKeyMap: SceneChart.Data = {}
77
- let value = []
78
-
79
- for (let key in array[0]) {
80
- indexKeyMap[key] = array[0][key]
81
- }
82
-
83
- for (var i = 1; i < array.length; i++) {
84
- let object: SceneChart.Data = {}
85
- let thisObject = array[i]
86
-
87
- for (let key in indexKeyMap) {
88
- let k = indexKeyMap[key]
89
- let v = thisObject[key]
90
- object[k] = v
91
- }
92
-
93
- value.push(object)
94
- }
95
-
96
- return value
97
- }
98
-
99
- function updateSeriesDatas(chartInstance: SceneChart) {
100
- if (!chartInstance.data.rawData) {
101
- return
102
- }
103
-
104
- let seriesData = chartInstance.data.rawData.seriesData
105
-
106
- if (!seriesData || seriesData.length === 0) seriesData = [null]
107
-
108
- for (let key in chartInstance.data.datasets) {
109
- chartInstance.data.datasets[Number(key)].data = seriesData[key] || []
110
- }
111
- }
112
-
113
- function updateLabelDatas(chartInstance: SceneChart) {
114
- let labelData = chartInstance.data.rawData.labelData
115
- chartInstance.config.data!.labels = labelData || []
116
- }
117
-
118
- export default {
119
- id: 'data-binder',
120
- beforeUpdate: function (chartInstance: SceneChart) {
121
- if (!chartInstance.data) return
122
-
123
- if (!chartInstance.data.rawData) chartInstance.data.rawData = []
124
-
125
- chartInstance.data.rawData = convertObject(chartInstance.data.rawData, chartInstance) || {
126
- seriesData: [],
127
- labelData: []
128
- }
129
-
130
- let seriesData = chartInstance.data.rawData.seriesData
131
- updateLabelDatas(chartInstance)
132
- updateSeriesDatas(chartInstance)
133
- }
134
- }
@@ -1,102 +0,0 @@
1
- declare class SceneChart extends Chart {
2
- type: Chart.ChartType | string
3
- data: SceneChart.ChartData
4
- }
5
-
6
- declare namespace SceneChart {
7
- type Theme = 'light' | 'dark'
8
- type Data = { [key: string]: any }
9
- type DataSeries = Array<Data>
10
-
11
- interface TickOptions extends Chart.TickOptions {
12
- autoMax?: boolean
13
- autoMin?: boolean
14
- }
15
-
16
- interface ChartScales {
17
- type?: Chart.ScaleType | string
18
- display?: boolean
19
- position?: Chart.PositionType | string
20
- gridLines?: GridLineOptions
21
- scaleLabel?: Chart.ScaleTitleOptions
22
- ticks?: TickOptions
23
- xAxes?: ChartXAxe[]
24
- yAxes?: ChartYAxe[]
25
- }
26
-
27
- interface ChartDataSets extends Chart.ChartDataSets {
28
- color: string
29
- dataKey: string
30
- valueFormat: string
31
- valuePrefix: string
32
- valueSuffix: string
33
- displayValue: string
34
- dataLabelAnchor: string
35
- dataLabelOffset?: number
36
- dataLabelRotation?: number
37
- defaultFontColor: string
38
- defaultFontSize: number
39
- highlight: {
40
- color: string
41
- condition: string
42
- }
43
- }
44
-
45
- interface ChartData {
46
- labels?: Array<string | string[]>
47
- datasets?: ChartDataSets[]
48
- rawData?: any
49
- labelDataKey?: string
50
- }
51
-
52
- interface ChartXAxe extends Chart.ChartXAxe {
53
- categorySpacing?: number
54
- barSpacing?: number
55
- ticks?: TickOptions
56
- axisTitle?: string
57
- }
58
- interface ChartYAxe extends ChartXAxe {}
59
-
60
- interface GridLineOptions extends Chart.GridLineOptions {}
61
- interface ChartLegendOptions extends Chart.ChartLegendOptions {}
62
- interface ChartTooltipOptions extends Chart.ChartTooltipOptions {}
63
- interface ChartTooltipItem extends Chart.ChartTooltipItem {}
64
- interface RadialLinearScale extends Chart.RadialLinearScale {}
65
- interface ChartPluginsOptions extends Chart.ChartPluginsOptions {}
66
-
67
- interface Context {
68
- dataset: ChartDataSets
69
- }
70
-
71
- interface DataLabelsPluginOptions {
72
- display: (context: Context) => true | false | 'auto'
73
- anchor: (context: Context) => 'center' | 'start' | 'end' | string
74
- color: (context: Context) => string
75
- font: (context: Context) => { size: number }
76
- clamp: boolean
77
- formatter: (value: any, context: Context) => string
78
- }
79
-
80
- interface ChartOptions extends Chart.ChartOptions {
81
- scales: ChartScales
82
- scale: RadialLinearScale
83
- legend: ChartLegendOptions
84
- tooltip: boolean /* show or hide tooltip */
85
- tooltips: ChartTooltipOptions
86
- multiAxis: boolean
87
- defaultFontSize: number | string
88
- defaultFontFamily: string
89
- defaultFontColor: string
90
- theme: Theme
91
- stacked?: boolean
92
- xGridLine: boolean
93
- fillStyle: string
94
- maintainAspectRatio?: boolean
95
- }
96
-
97
- interface ChartConfig {
98
- type: string
99
- data: ChartData
100
- options: ChartOptions
101
- }
102
- }
@@ -1,121 +0,0 @@
1
- const icon = new URL('../../icons/bar-chart.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'bar-chart',
5
- description: 'ChartJS - barchart',
6
- icon: icon,
7
- group: 'chartAndGauge',
8
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
9
- model: {
10
- type: 'chartjs',
11
- top: 200,
12
- left: 300,
13
- width: 200,
14
- height: 200,
15
- chart: {
16
- type: 'bar',
17
- data: {
18
- labels: [],
19
- datasets: [
20
- {
21
- label: 'series 1',
22
- type: 'bar',
23
- data: [],
24
- backgroundColor: 'rgb(66, 110, 164)',
25
- borderColor: 'rgb(66, 110, 164)',
26
- borderWidth: 0,
27
- dataKey: 'value',
28
- yAxisID: 'left'
29
- }
30
- ],
31
- labelDataKey: 'color'
32
- },
33
- options: {
34
- theme: 'dark',
35
- xGridLine: false,
36
- yGridLine: true,
37
- legend: {
38
- display: true,
39
- position: 'top'
40
- },
41
- scales: {
42
- xAxes: [
43
- {
44
- gridLines: {
45
- display: false
46
- },
47
- scaleLabel: {
48
- labelString: '',
49
- display: false
50
- },
51
- ticks: {
52
- display: true
53
- }
54
- }
55
- ],
56
- yAxes: [
57
- {
58
- id: 'left',
59
- position: 'left',
60
- gridLines: {
61
- display: true
62
- },
63
- scaleLabel: {
64
- labelString: '',
65
- display: false
66
- },
67
- ticks: {
68
- autoMin: true,
69
- autoMax: true,
70
- display: true
71
- }
72
- },
73
- {
74
- id: 'right',
75
- position: 'right',
76
- display: false,
77
- gridLines: {
78
- display: false
79
- },
80
- scaleLabel: {
81
- labelString: '',
82
- display: false
83
- },
84
- ticks: {
85
- autoMin: true,
86
- autoMax: true,
87
- display: true
88
- }
89
- }
90
- ]
91
- }
92
- }
93
- },
94
- data: [
95
- {
96
- color: 'Red',
97
- value: 12
98
- },
99
- {
100
- color: 'Blue',
101
- value: 19
102
- },
103
- {
104
- color: 'Yellow',
105
- value: 3
106
- },
107
- {
108
- color: 'Green',
109
- value: 5
110
- },
111
- {
112
- color: 'Purple',
113
- value: 2
114
- },
115
- {
116
- color: 'Orange',
117
- value: 3
118
- }
119
- ]
120
- }
121
- }
@@ -1,55 +0,0 @@
1
- const icon = new URL('../../icons/doughnut-chart.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'doughnut-chart',
5
- description: 'ChartJS - doughnut',
6
- icon: icon,
7
- group: 'chartAndGauge',
8
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
9
- model: {
10
- type: 'chartjs',
11
- top: 0,
12
- left: 0,
13
- width: 200,
14
- height: 200,
15
- chart: {
16
- type: 'doughnut',
17
- data: {
18
- labels: [],
19
- datasets: [
20
- {
21
- data: [],
22
- backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
23
- borderWidth: 0,
24
- dataKey: 'value'
25
- }
26
- ],
27
- labelDataKey: 'label'
28
- },
29
- options: {
30
- theme: 'dark',
31
- legend: {
32
- display: true,
33
- position: 'top'
34
- },
35
- animation: {
36
- animateScale: true
37
- }
38
- }
39
- },
40
- data: [
41
- {
42
- label: 'Red',
43
- value: 300
44
- },
45
- {
46
- label: 'Blue',
47
- value: 50
48
- },
49
- {
50
- label: 'Yellow',
51
- value: 100
52
- }
53
- ]
54
- }
55
- }