@orbcharts/core 3.0.0-beta.1 → 3.0.0-beta.2
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/LICENSE +200 -200
- package/dist/orbcharts-core.es.js +4 -3
- package/dist/orbcharts-core.umd.js +1 -1
- package/lib/core-types.ts +7 -7
- package/package.json +42 -42
- package/src/AbstractChart.ts +57 -57
- package/src/GridChart.ts +24 -24
- package/src/MultiGridChart.ts +24 -24
- package/src/MultiValueChart.ts +24 -24
- package/src/RelationshipChart.ts +24 -24
- package/src/SeriesChart.ts +24 -24
- package/src/TreeChart.ts +24 -24
- package/src/base/createBaseChart.ts +505 -505
- package/src/base/createBasePlugin.ts +153 -153
- package/src/base/validators/chartOptionsValidator.ts +23 -23
- package/src/base/validators/chartParamsValidator.ts +133 -133
- package/src/base/validators/elementValidator.ts +13 -13
- package/src/base/validators/pluginsValidator.ts +14 -14
- package/src/defaults.ts +232 -232
- package/src/defineGridPlugin.ts +3 -3
- package/src/defineMultiGridPlugin.ts +3 -3
- package/src/defineMultiValuePlugin.ts +3 -3
- package/src/defineNoneDataPlugin.ts +4 -4
- package/src/defineRelationshipPlugin.ts +3 -3
- package/src/defineSeriesPlugin.ts +3 -3
- package/src/defineTreePlugin.ts +3 -3
- package/src/grid/computedDataFn.ts +129 -129
- package/src/grid/contextObserverCallback.ts +155 -155
- package/src/grid/dataFormatterValidator.ts +101 -101
- package/src/grid/dataValidator.ts +12 -12
- package/src/index.ts +20 -20
- package/src/multiGrid/computedDataFn.ts +123 -123
- package/src/multiGrid/contextObserverCallback.ts +41 -41
- package/src/multiGrid/dataFormatterValidator.ts +115 -115
- package/src/multiGrid/dataValidator.ts +12 -12
- package/src/multiValue/computedDataFn.ts +176 -176
- package/src/multiValue/contextObserverCallback.ts +12 -12
- package/src/multiValue/dataFormatterValidator.ts +9 -9
- package/src/multiValue/dataValidator.ts +9 -9
- package/src/relationship/computedDataFn.ts +125 -125
- package/src/relationship/contextObserverCallback.ts +12 -12
- package/src/relationship/dataFormatterValidator.ts +9 -9
- package/src/relationship/dataValidator.ts +9 -9
- package/src/series/computedDataFn.ts +88 -88
- package/src/series/contextObserverCallback.ts +100 -100
- package/src/series/dataFormatterValidator.ts +41 -41
- package/src/series/dataValidator.ts +12 -12
- package/src/tree/computedDataFn.ts +130 -130
- package/src/tree/contextObserverCallback.ts +61 -61
- package/src/tree/dataFormatterValidator.ts +13 -13
- package/src/tree/dataValidator.ts +13 -13
- package/src/utils/commonUtils.ts +55 -55
- package/src/utils/d3Utils.ts +108 -108
- package/src/utils/errorMessage.ts +42 -42
- package/src/utils/gridObservables.ts +614 -611
- package/src/utils/index.ts +9 -9
- package/src/utils/multiGridObservables.ts +366 -366
- package/src/utils/observables.ts +219 -219
- package/src/utils/orbchartsUtils.ts +352 -352
- package/src/utils/seriesObservables.ts +175 -175
- package/src/utils/treeObservables.ts +94 -94
- package/src/utils/validator.ts +125 -125
- package/tsconfig.base.json +13 -13
- package/tsconfig.json +2 -2
- package/vite-env.d.ts +6 -6
- package/vite.config.js +22 -22
@@ -1,116 +1,116 @@
|
|
1
|
-
import type { DataFormatterValidator, DataFormatterTypeMap, ValidatorResult } from '../../lib/core-types'
|
2
|
-
import { validateColumns } from '../utils/validator'
|
3
|
-
|
4
|
-
export const dataFormatterValidator: DataFormatterValidator<'multiGrid'> = (dataFormatter: DataFormatterTypeMap<'multiGrid'>) => {
|
5
|
-
const result = validateColumns(dataFormatter, {
|
6
|
-
visibleFilter: {
|
7
|
-
toBeTypes: ['Function']
|
8
|
-
},
|
9
|
-
gridList: {
|
10
|
-
toBeTypes: ['object[]']
|
11
|
-
},
|
12
|
-
container: {
|
13
|
-
toBeTypes: ['object']
|
14
|
-
},
|
15
|
-
separateGrid: {
|
16
|
-
toBeTypes: ['boolean']
|
17
|
-
}
|
18
|
-
})
|
19
|
-
if (dataFormatter.gridList) {
|
20
|
-
const gridListResultArr = dataFormatter.gridList.map((grid, index) => {
|
21
|
-
const gridResult = validateColumns(grid, {
|
22
|
-
seriesDirection: {
|
23
|
-
toBe: '"row" | "column"',
|
24
|
-
test: (value) => value === 'row' || value === 'column'
|
25
|
-
},
|
26
|
-
rowLabels: {
|
27
|
-
toBeTypes: ['string[]']
|
28
|
-
},
|
29
|
-
columnLabels: {
|
30
|
-
toBeTypes: ['string[]']
|
31
|
-
},
|
32
|
-
valueAxis: {
|
33
|
-
toBeTypes: ['object']
|
34
|
-
},
|
35
|
-
groupAxis: {
|
36
|
-
toBeTypes: ['object']
|
37
|
-
},
|
38
|
-
separateSeries: {
|
39
|
-
toBeTypes: ['boolean']
|
40
|
-
}
|
41
|
-
})
|
42
|
-
if (gridResult.status === 'error') {
|
43
|
-
return gridResult
|
44
|
-
} else {
|
45
|
-
if (grid.valueAxis) {
|
46
|
-
const valueAxisResult = validateColumns(grid.valueAxis, {
|
47
|
-
position: {
|
48
|
-
toBe: '"top" | "bottom" | "left" | "right"',
|
49
|
-
test: (value) => value === 'top' || value === 'bottom' || value === 'left' || value === 'right'
|
50
|
-
},
|
51
|
-
scaleDomain: {
|
52
|
-
toBe: '[number | "min" | "auto", number | "max" | "auto"]',
|
53
|
-
test: (value) => Array.isArray(value) && value.length === 2 && (typeof value[0] === 'number' || value[0] === 'min' || value[0] === 'auto') && (typeof value[1] === 'number' || value[1] === 'max' || value[1] === 'auto')
|
54
|
-
},
|
55
|
-
scaleRange: {
|
56
|
-
toBe: '[number, number]',
|
57
|
-
test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number'
|
58
|
-
},
|
59
|
-
label: {
|
60
|
-
toBeTypes: ['string']
|
61
|
-
}
|
62
|
-
})
|
63
|
-
if (valueAxisResult.status === 'error') {
|
64
|
-
return valueAxisResult
|
65
|
-
}
|
66
|
-
} else if (grid.groupAxis) {
|
67
|
-
const groupAxisResult = validateColumns(grid.groupAxis, {
|
68
|
-
position: {
|
69
|
-
toBe: '"top" | "bottom" | "left" | "right"',
|
70
|
-
test: (value) => value === 'top' || value === 'bottom' || value === 'left' || value === 'right'
|
71
|
-
},
|
72
|
-
scaleDomain: {
|
73
|
-
toBe: '[number, number | "max"]',
|
74
|
-
test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && (typeof value[1] === 'number' || value[1] === 'max')
|
75
|
-
},
|
76
|
-
scalePadding: {
|
77
|
-
toBeTypes: ['number']
|
78
|
-
},
|
79
|
-
label: {
|
80
|
-
toBeTypes: ['string']
|
81
|
-
}
|
82
|
-
})
|
83
|
-
if (groupAxisResult.status === 'error') {
|
84
|
-
return groupAxisResult
|
85
|
-
}
|
86
|
-
}
|
87
|
-
return <ValidatorResult>{
|
88
|
-
status: 'success',
|
89
|
-
columnName: '',
|
90
|
-
expectToBe: ''
|
91
|
-
}
|
92
|
-
}
|
93
|
-
})
|
94
|
-
const gridListResult = gridListResultArr.find((gridResult) => gridResult.status === 'error')
|
95
|
-
if (gridListResult) {
|
96
|
-
return gridListResult
|
97
|
-
}
|
98
|
-
}
|
99
|
-
if (dataFormatter.container) {
|
100
|
-
const containerResult = validateColumns(dataFormatter.container, {
|
101
|
-
gap: {
|
102
|
-
toBeTypes: ['number']
|
103
|
-
},
|
104
|
-
rowAmount: {
|
105
|
-
toBeTypes: ['number']
|
106
|
-
},
|
107
|
-
columnAmount: {
|
108
|
-
toBeTypes: ['number']
|
109
|
-
}
|
110
|
-
})
|
111
|
-
if (containerResult.status === 'error') {
|
112
|
-
return containerResult
|
113
|
-
}
|
114
|
-
}
|
115
|
-
return result
|
1
|
+
import type { DataFormatterValidator, DataFormatterTypeMap, ValidatorResult } from '../../lib/core-types'
|
2
|
+
import { validateColumns } from '../utils/validator'
|
3
|
+
|
4
|
+
export const dataFormatterValidator: DataFormatterValidator<'multiGrid'> = (dataFormatter: DataFormatterTypeMap<'multiGrid'>) => {
|
5
|
+
const result = validateColumns(dataFormatter, {
|
6
|
+
visibleFilter: {
|
7
|
+
toBeTypes: ['Function']
|
8
|
+
},
|
9
|
+
gridList: {
|
10
|
+
toBeTypes: ['object[]']
|
11
|
+
},
|
12
|
+
container: {
|
13
|
+
toBeTypes: ['object']
|
14
|
+
},
|
15
|
+
separateGrid: {
|
16
|
+
toBeTypes: ['boolean']
|
17
|
+
}
|
18
|
+
})
|
19
|
+
if (dataFormatter.gridList) {
|
20
|
+
const gridListResultArr = dataFormatter.gridList.map((grid, index) => {
|
21
|
+
const gridResult = validateColumns(grid, {
|
22
|
+
seriesDirection: {
|
23
|
+
toBe: '"row" | "column"',
|
24
|
+
test: (value) => value === 'row' || value === 'column'
|
25
|
+
},
|
26
|
+
rowLabels: {
|
27
|
+
toBeTypes: ['string[]']
|
28
|
+
},
|
29
|
+
columnLabels: {
|
30
|
+
toBeTypes: ['string[]']
|
31
|
+
},
|
32
|
+
valueAxis: {
|
33
|
+
toBeTypes: ['object']
|
34
|
+
},
|
35
|
+
groupAxis: {
|
36
|
+
toBeTypes: ['object']
|
37
|
+
},
|
38
|
+
separateSeries: {
|
39
|
+
toBeTypes: ['boolean']
|
40
|
+
}
|
41
|
+
})
|
42
|
+
if (gridResult.status === 'error') {
|
43
|
+
return gridResult
|
44
|
+
} else {
|
45
|
+
if (grid.valueAxis) {
|
46
|
+
const valueAxisResult = validateColumns(grid.valueAxis, {
|
47
|
+
position: {
|
48
|
+
toBe: '"top" | "bottom" | "left" | "right"',
|
49
|
+
test: (value) => value === 'top' || value === 'bottom' || value === 'left' || value === 'right'
|
50
|
+
},
|
51
|
+
scaleDomain: {
|
52
|
+
toBe: '[number | "min" | "auto", number | "max" | "auto"]',
|
53
|
+
test: (value) => Array.isArray(value) && value.length === 2 && (typeof value[0] === 'number' || value[0] === 'min' || value[0] === 'auto') && (typeof value[1] === 'number' || value[1] === 'max' || value[1] === 'auto')
|
54
|
+
},
|
55
|
+
scaleRange: {
|
56
|
+
toBe: '[number, number]',
|
57
|
+
test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number'
|
58
|
+
},
|
59
|
+
label: {
|
60
|
+
toBeTypes: ['string']
|
61
|
+
}
|
62
|
+
})
|
63
|
+
if (valueAxisResult.status === 'error') {
|
64
|
+
return valueAxisResult
|
65
|
+
}
|
66
|
+
} else if (grid.groupAxis) {
|
67
|
+
const groupAxisResult = validateColumns(grid.groupAxis, {
|
68
|
+
position: {
|
69
|
+
toBe: '"top" | "bottom" | "left" | "right"',
|
70
|
+
test: (value) => value === 'top' || value === 'bottom' || value === 'left' || value === 'right'
|
71
|
+
},
|
72
|
+
scaleDomain: {
|
73
|
+
toBe: '[number, number | "max"]',
|
74
|
+
test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && (typeof value[1] === 'number' || value[1] === 'max')
|
75
|
+
},
|
76
|
+
scalePadding: {
|
77
|
+
toBeTypes: ['number']
|
78
|
+
},
|
79
|
+
label: {
|
80
|
+
toBeTypes: ['string']
|
81
|
+
}
|
82
|
+
})
|
83
|
+
if (groupAxisResult.status === 'error') {
|
84
|
+
return groupAxisResult
|
85
|
+
}
|
86
|
+
}
|
87
|
+
return <ValidatorResult>{
|
88
|
+
status: 'success',
|
89
|
+
columnName: '',
|
90
|
+
expectToBe: ''
|
91
|
+
}
|
92
|
+
}
|
93
|
+
})
|
94
|
+
const gridListResult = gridListResultArr.find((gridResult) => gridResult.status === 'error')
|
95
|
+
if (gridListResult) {
|
96
|
+
return gridListResult
|
97
|
+
}
|
98
|
+
}
|
99
|
+
if (dataFormatter.container) {
|
100
|
+
const containerResult = validateColumns(dataFormatter.container, {
|
101
|
+
gap: {
|
102
|
+
toBeTypes: ['number']
|
103
|
+
},
|
104
|
+
rowAmount: {
|
105
|
+
toBeTypes: ['number']
|
106
|
+
},
|
107
|
+
columnAmount: {
|
108
|
+
toBeTypes: ['number']
|
109
|
+
}
|
110
|
+
})
|
111
|
+
if (containerResult.status === 'error') {
|
112
|
+
return containerResult
|
113
|
+
}
|
114
|
+
}
|
115
|
+
return result
|
116
116
|
}
|
@@ -1,13 +1,13 @@
|
|
1
|
-
import type { DataValidator, DataTypeMap } from '../../lib/core-types'
|
2
|
-
import { validateColumns } from '../utils/validator'
|
3
|
-
|
4
|
-
export const dataValidator: DataValidator<'multiGrid'> = (data: DataTypeMap<'multiGrid'>) => {
|
5
|
-
const result = validateColumns({ data }, {
|
6
|
-
data: {
|
7
|
-
toBe: 'DataGrid[]',
|
8
|
-
// 畢免資料量過大檢查不完,不深度檢查
|
9
|
-
test: (value) => Array.isArray(value)
|
10
|
-
}
|
11
|
-
})
|
12
|
-
return result
|
1
|
+
import type { DataValidator, DataTypeMap } from '../../lib/core-types'
|
2
|
+
import { validateColumns } from '../utils/validator'
|
3
|
+
|
4
|
+
export const dataValidator: DataValidator<'multiGrid'> = (data: DataTypeMap<'multiGrid'>) => {
|
5
|
+
const result = validateColumns({ data }, {
|
6
|
+
data: {
|
7
|
+
toBe: 'DataGrid[]',
|
8
|
+
// 畢免資料量過大檢查不完,不深度檢查
|
9
|
+
test: (value) => Array.isArray(value)
|
10
|
+
}
|
11
|
+
})
|
12
|
+
return result
|
13
13
|
}
|
@@ -1,176 +1,176 @@
|
|
1
|
-
import type { DataMultiValueDatum, ComputedDataFn, ComputedDatumMultiValue } from '../../lib/core-types'
|
2
|
-
import { formatValueToLabel, createDefaultDatumId } from '../utils/orbchartsUtils'
|
3
|
-
import { createAxisLinearScale, createAxisPointScale } from '../utils/d3Utils'
|
4
|
-
import { getMinAndMaxValue } from '../utils/orbchartsUtils'
|
5
|
-
|
6
|
-
export const computedDataFn: ComputedDataFn<'multiValue'> = (context) => {
|
7
|
-
const { data, dataFormatter, chartParams } = context
|
8
|
-
if (!data.length) {
|
9
|
-
return []
|
10
|
-
}
|
11
|
-
|
12
|
-
// @Q@ 假資料待改寫
|
13
|
-
const layout = {
|
14
|
-
width: 1000,
|
15
|
-
height: 1000
|
16
|
-
}
|
17
|
-
|
18
|
-
let computedDataMultiValue: ComputedDatumMultiValue[][] = []
|
19
|
-
|
20
|
-
try {
|
21
|
-
const dataMultiValue: DataMultiValueDatum[][] = data.map((d, i) => {
|
22
|
-
return d.map((_d, _i) => {
|
23
|
-
const datum: DataMultiValueDatum = typeof _d === 'number'
|
24
|
-
? {
|
25
|
-
id: '',
|
26
|
-
label: '',
|
27
|
-
description: '',
|
28
|
-
// tooltipContent: '',
|
29
|
-
data: {},
|
30
|
-
categoryLabel: '',
|
31
|
-
value: _d
|
32
|
-
}
|
33
|
-
: {
|
34
|
-
id: _d.id ?? '',
|
35
|
-
label: _d.label ?? '',
|
36
|
-
description: _d.description ?? '',
|
37
|
-
// tooltipContent: _d.tooltipContent ?? '',
|
38
|
-
data: _d.data ?? {},
|
39
|
-
categoryLabel: _d.categoryLabel ??'',
|
40
|
-
value: _d.value
|
41
|
-
}
|
42
|
-
|
43
|
-
return datum
|
44
|
-
})
|
45
|
-
})
|
46
|
-
|
47
|
-
// x軸資料最小及最大值(第二維陣列中的第1筆為x軸資料)
|
48
|
-
const [xMinValue, xMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[0]))
|
49
|
-
// y軸資料最小及最大值(第二維陣列中的第2筆為y軸資料)
|
50
|
-
const [yMinValue, yMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[1]))
|
51
|
-
|
52
|
-
// const axisWidth = layout.width - dataFormatter.padding.left - dataFormatter.padding.right
|
53
|
-
// const axisHeight = layout.height - dataFormatter.padding.top - dataFormatter.padding.bottom
|
54
|
-
// const axisWidth = layout.width
|
55
|
-
// const axisHeight = layout.height
|
56
|
-
const xAxisWidth = (dataFormatter.xAxis.position === 'top' || dataFormatter.xAxis.position === 'bottom')
|
57
|
-
? layout.width
|
58
|
-
: layout.height
|
59
|
-
const yAxisWidth = (dataFormatter.yAxis.position === 'left' || dataFormatter.yAxis.position === 'right')
|
60
|
-
? layout.height
|
61
|
-
: layout.width
|
62
|
-
|
63
|
-
const xScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
|
64
|
-
maxValue: xMaxValue,
|
65
|
-
minValue: xMinValue,
|
66
|
-
axisWidth: xAxisWidth,
|
67
|
-
// scaleDomain: dataFormatter.xAxis.scaleDomain,
|
68
|
-
// scaleRange: dataFormatter.xAxis.scaleRange
|
69
|
-
scaleDomain: [xMinValue, xMaxValue],
|
70
|
-
scaleRange: [0, 1]
|
71
|
-
})
|
72
|
-
const yScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
|
73
|
-
maxValue: yMaxValue,
|
74
|
-
minValue: yMinValue,
|
75
|
-
axisWidth: yAxisWidth,
|
76
|
-
// scaleDomain: dataFormatter.yAxis.scaleDomain,
|
77
|
-
// scaleRange: dataFormatter.yAxis.scaleRange
|
78
|
-
scaleDomain: [yMinValue, yMaxValue],
|
79
|
-
scaleRange: [0, 1]
|
80
|
-
})
|
81
|
-
|
82
|
-
const _xScaleDoamin: [number, number] = [
|
83
|
-
// dataFormatter.xAxis.scaleDomain[0] === 'auto' ? xMinValue : dataFormatter.xAxis.scaleDomain[0],
|
84
|
-
(() => {
|
85
|
-
if (dataFormatter.xAxis.scaleDomain[0] === 'auto') {
|
86
|
-
return xMinValue < 0 ? xMinValue : 0
|
87
|
-
} else if (dataFormatter.xAxis.scaleDomain[0] === 'min') {
|
88
|
-
return xMinValue
|
89
|
-
} else {
|
90
|
-
return dataFormatter.xAxis.scaleDomain[0]
|
91
|
-
}
|
92
|
-
})(),
|
93
|
-
// dataFormatter.xAxis.scaleDomain[1] === 'auto' ? xMaxValue : dataFormatter.xAxis.scaleDomain[1]
|
94
|
-
(() => {
|
95
|
-
if (dataFormatter.xAxis.scaleDomain[1] === 'auto') {
|
96
|
-
return xMaxValue >= 0 ? xMaxValue : 0
|
97
|
-
} else if (dataFormatter.xAxis.scaleDomain[1] === 'max') {
|
98
|
-
return xMaxValue
|
99
|
-
} else {
|
100
|
-
return dataFormatter.xAxis.scaleDomain[1]
|
101
|
-
}
|
102
|
-
})()
|
103
|
-
]
|
104
|
-
const _yScaleDoamin: [number, number] = [
|
105
|
-
// dataFormatter.yAxis.scaleDomain[0] === 'auto' ? yMinValue : dataFormatter.yAxis.scaleDomain[0],
|
106
|
-
(() => {
|
107
|
-
if (dataFormatter.yAxis.scaleDomain[0] === 'auto') {
|
108
|
-
return xMinValue < 0 ? xMinValue : 0
|
109
|
-
} else if (dataFormatter.yAxis.scaleDomain[0] === 'min') {
|
110
|
-
return xMinValue
|
111
|
-
} else {
|
112
|
-
return dataFormatter.yAxis.scaleDomain[0]
|
113
|
-
}
|
114
|
-
})(),
|
115
|
-
// dataFormatter.yAxis.scaleDomain[1] === 'auto' ? yMaxValue : dataFormatter.yAxis.scaleDomain[1]
|
116
|
-
(() => {
|
117
|
-
if (dataFormatter.yAxis.scaleDomain[1] === 'auto') {
|
118
|
-
return xMaxValue >= 0 ? xMaxValue : 0
|
119
|
-
} else if (dataFormatter.yAxis.scaleDomain[1] === 'max') {
|
120
|
-
return xMaxValue
|
121
|
-
} else {
|
122
|
-
return dataFormatter.yAxis.scaleDomain[1]
|
123
|
-
}
|
124
|
-
})()
|
125
|
-
]
|
126
|
-
|
127
|
-
// // 篩選顯示狀態
|
128
|
-
// const visibleFilter = (datum: DataMultiValueDatum, rowIndex: number, columnIndex: number, context: DataFormatterContext<"multiValue">) => {
|
129
|
-
// // 如果不在scale的範圍內則為false,不再做visibleFilter的判斷
|
130
|
-
// if (columnIndex === 0 && datum.value != null && ((datum.value as number) < _xScaleDoamin[0] || datum.value > _xScaleDoamin[1])) {
|
131
|
-
// return false
|
132
|
-
// }
|
133
|
-
// if (columnIndex === 1 && datum.value != null && (datum.value < _yScaleDoamin[0] || datum.value > _yScaleDoamin[1])) {
|
134
|
-
// return false
|
135
|
-
// }
|
136
|
-
|
137
|
-
// return dataFormatter.visibleFilter(datum, rowIndex, columnIndex, context)
|
138
|
-
// }
|
139
|
-
|
140
|
-
let index = 0
|
141
|
-
|
142
|
-
computedDataMultiValue = dataMultiValue.map((d, i) => {
|
143
|
-
return d.map((_d, _i) => {
|
144
|
-
const currentIndex = index
|
145
|
-
index++
|
146
|
-
|
147
|
-
const defaultId = createDefaultDatumId(dataFormatter.type, i, _i)
|
148
|
-
|
149
|
-
const computedDatum: ComputedDatumMultiValue = {
|
150
|
-
id: _d.id ? _d.id : defaultId,
|
151
|
-
index: currentIndex,
|
152
|
-
label: _d.label ? _d.label : defaultId,
|
153
|
-
description: _d.description ?? '',
|
154
|
-
// tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
|
155
|
-
data: _d.data,
|
156
|
-
value: _d.value,
|
157
|
-
categoryIndex: 0, // @Q@ 未完成
|
158
|
-
categoryLabel: '', // @Q@ 未完成
|
159
|
-
// valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
|
160
|
-
axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
|
161
|
-
visible: true, // 先給預設值
|
162
|
-
color: '' // @Q@ 未完成
|
163
|
-
}
|
164
|
-
|
165
|
-
computedDatum.visible = dataFormatter.visibleFilter(computedDatum, context)
|
166
|
-
|
167
|
-
return computedDatum
|
168
|
-
})
|
169
|
-
})
|
170
|
-
} catch (e) {
|
171
|
-
// console.error(e)
|
172
|
-
throw Error(e)
|
173
|
-
}
|
174
|
-
|
175
|
-
return computedDataMultiValue
|
176
|
-
}
|
1
|
+
import type { DataMultiValueDatum, ComputedDataFn, ComputedDatumMultiValue } from '../../lib/core-types'
|
2
|
+
import { formatValueToLabel, createDefaultDatumId } from '../utils/orbchartsUtils'
|
3
|
+
import { createAxisLinearScale, createAxisPointScale } from '../utils/d3Utils'
|
4
|
+
import { getMinAndMaxValue } from '../utils/orbchartsUtils'
|
5
|
+
|
6
|
+
export const computedDataFn: ComputedDataFn<'multiValue'> = (context) => {
|
7
|
+
const { data, dataFormatter, chartParams } = context
|
8
|
+
if (!data.length) {
|
9
|
+
return []
|
10
|
+
}
|
11
|
+
|
12
|
+
// @Q@ 假資料待改寫
|
13
|
+
const layout = {
|
14
|
+
width: 1000,
|
15
|
+
height: 1000
|
16
|
+
}
|
17
|
+
|
18
|
+
let computedDataMultiValue: ComputedDatumMultiValue[][] = []
|
19
|
+
|
20
|
+
try {
|
21
|
+
const dataMultiValue: DataMultiValueDatum[][] = data.map((d, i) => {
|
22
|
+
return d.map((_d, _i) => {
|
23
|
+
const datum: DataMultiValueDatum = typeof _d === 'number'
|
24
|
+
? {
|
25
|
+
id: '',
|
26
|
+
label: '',
|
27
|
+
description: '',
|
28
|
+
// tooltipContent: '',
|
29
|
+
data: {},
|
30
|
+
categoryLabel: '',
|
31
|
+
value: _d
|
32
|
+
}
|
33
|
+
: {
|
34
|
+
id: _d.id ?? '',
|
35
|
+
label: _d.label ?? '',
|
36
|
+
description: _d.description ?? '',
|
37
|
+
// tooltipContent: _d.tooltipContent ?? '',
|
38
|
+
data: _d.data ?? {},
|
39
|
+
categoryLabel: _d.categoryLabel ??'',
|
40
|
+
value: _d.value
|
41
|
+
}
|
42
|
+
|
43
|
+
return datum
|
44
|
+
})
|
45
|
+
})
|
46
|
+
|
47
|
+
// x軸資料最小及最大值(第二維陣列中的第1筆為x軸資料)
|
48
|
+
const [xMinValue, xMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[0]))
|
49
|
+
// y軸資料最小及最大值(第二維陣列中的第2筆為y軸資料)
|
50
|
+
const [yMinValue, yMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[1]))
|
51
|
+
|
52
|
+
// const axisWidth = layout.width - dataFormatter.padding.left - dataFormatter.padding.right
|
53
|
+
// const axisHeight = layout.height - dataFormatter.padding.top - dataFormatter.padding.bottom
|
54
|
+
// const axisWidth = layout.width
|
55
|
+
// const axisHeight = layout.height
|
56
|
+
const xAxisWidth = (dataFormatter.xAxis.position === 'top' || dataFormatter.xAxis.position === 'bottom')
|
57
|
+
? layout.width
|
58
|
+
: layout.height
|
59
|
+
const yAxisWidth = (dataFormatter.yAxis.position === 'left' || dataFormatter.yAxis.position === 'right')
|
60
|
+
? layout.height
|
61
|
+
: layout.width
|
62
|
+
|
63
|
+
const xScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
|
64
|
+
maxValue: xMaxValue,
|
65
|
+
minValue: xMinValue,
|
66
|
+
axisWidth: xAxisWidth,
|
67
|
+
// scaleDomain: dataFormatter.xAxis.scaleDomain,
|
68
|
+
// scaleRange: dataFormatter.xAxis.scaleRange
|
69
|
+
scaleDomain: [xMinValue, xMaxValue],
|
70
|
+
scaleRange: [0, 1]
|
71
|
+
})
|
72
|
+
const yScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
|
73
|
+
maxValue: yMaxValue,
|
74
|
+
minValue: yMinValue,
|
75
|
+
axisWidth: yAxisWidth,
|
76
|
+
// scaleDomain: dataFormatter.yAxis.scaleDomain,
|
77
|
+
// scaleRange: dataFormatter.yAxis.scaleRange
|
78
|
+
scaleDomain: [yMinValue, yMaxValue],
|
79
|
+
scaleRange: [0, 1]
|
80
|
+
})
|
81
|
+
|
82
|
+
const _xScaleDoamin: [number, number] = [
|
83
|
+
// dataFormatter.xAxis.scaleDomain[0] === 'auto' ? xMinValue : dataFormatter.xAxis.scaleDomain[0],
|
84
|
+
(() => {
|
85
|
+
if (dataFormatter.xAxis.scaleDomain[0] === 'auto') {
|
86
|
+
return xMinValue < 0 ? xMinValue : 0
|
87
|
+
} else if (dataFormatter.xAxis.scaleDomain[0] === 'min') {
|
88
|
+
return xMinValue
|
89
|
+
} else {
|
90
|
+
return dataFormatter.xAxis.scaleDomain[0]
|
91
|
+
}
|
92
|
+
})(),
|
93
|
+
// dataFormatter.xAxis.scaleDomain[1] === 'auto' ? xMaxValue : dataFormatter.xAxis.scaleDomain[1]
|
94
|
+
(() => {
|
95
|
+
if (dataFormatter.xAxis.scaleDomain[1] === 'auto') {
|
96
|
+
return xMaxValue >= 0 ? xMaxValue : 0
|
97
|
+
} else if (dataFormatter.xAxis.scaleDomain[1] === 'max') {
|
98
|
+
return xMaxValue
|
99
|
+
} else {
|
100
|
+
return dataFormatter.xAxis.scaleDomain[1]
|
101
|
+
}
|
102
|
+
})()
|
103
|
+
]
|
104
|
+
const _yScaleDoamin: [number, number] = [
|
105
|
+
// dataFormatter.yAxis.scaleDomain[0] === 'auto' ? yMinValue : dataFormatter.yAxis.scaleDomain[0],
|
106
|
+
(() => {
|
107
|
+
if (dataFormatter.yAxis.scaleDomain[0] === 'auto') {
|
108
|
+
return xMinValue < 0 ? xMinValue : 0
|
109
|
+
} else if (dataFormatter.yAxis.scaleDomain[0] === 'min') {
|
110
|
+
return xMinValue
|
111
|
+
} else {
|
112
|
+
return dataFormatter.yAxis.scaleDomain[0]
|
113
|
+
}
|
114
|
+
})(),
|
115
|
+
// dataFormatter.yAxis.scaleDomain[1] === 'auto' ? yMaxValue : dataFormatter.yAxis.scaleDomain[1]
|
116
|
+
(() => {
|
117
|
+
if (dataFormatter.yAxis.scaleDomain[1] === 'auto') {
|
118
|
+
return xMaxValue >= 0 ? xMaxValue : 0
|
119
|
+
} else if (dataFormatter.yAxis.scaleDomain[1] === 'max') {
|
120
|
+
return xMaxValue
|
121
|
+
} else {
|
122
|
+
return dataFormatter.yAxis.scaleDomain[1]
|
123
|
+
}
|
124
|
+
})()
|
125
|
+
]
|
126
|
+
|
127
|
+
// // 篩選顯示狀態
|
128
|
+
// const visibleFilter = (datum: DataMultiValueDatum, rowIndex: number, columnIndex: number, context: DataFormatterContext<"multiValue">) => {
|
129
|
+
// // 如果不在scale的範圍內則為false,不再做visibleFilter的判斷
|
130
|
+
// if (columnIndex === 0 && datum.value != null && ((datum.value as number) < _xScaleDoamin[0] || datum.value > _xScaleDoamin[1])) {
|
131
|
+
// return false
|
132
|
+
// }
|
133
|
+
// if (columnIndex === 1 && datum.value != null && (datum.value < _yScaleDoamin[0] || datum.value > _yScaleDoamin[1])) {
|
134
|
+
// return false
|
135
|
+
// }
|
136
|
+
|
137
|
+
// return dataFormatter.visibleFilter(datum, rowIndex, columnIndex, context)
|
138
|
+
// }
|
139
|
+
|
140
|
+
let index = 0
|
141
|
+
|
142
|
+
computedDataMultiValue = dataMultiValue.map((d, i) => {
|
143
|
+
return d.map((_d, _i) => {
|
144
|
+
const currentIndex = index
|
145
|
+
index++
|
146
|
+
|
147
|
+
const defaultId = createDefaultDatumId(dataFormatter.type, i, _i)
|
148
|
+
|
149
|
+
const computedDatum: ComputedDatumMultiValue = {
|
150
|
+
id: _d.id ? _d.id : defaultId,
|
151
|
+
index: currentIndex,
|
152
|
+
label: _d.label ? _d.label : defaultId,
|
153
|
+
description: _d.description ?? '',
|
154
|
+
// tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
|
155
|
+
data: _d.data,
|
156
|
+
value: _d.value,
|
157
|
+
categoryIndex: 0, // @Q@ 未完成
|
158
|
+
categoryLabel: '', // @Q@ 未完成
|
159
|
+
// valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
|
160
|
+
axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
|
161
|
+
visible: true, // 先給預設值
|
162
|
+
color: '' // @Q@ 未完成
|
163
|
+
}
|
164
|
+
|
165
|
+
computedDatum.visible = dataFormatter.visibleFilter(computedDatum, context)
|
166
|
+
|
167
|
+
return computedDatum
|
168
|
+
})
|
169
|
+
})
|
170
|
+
} catch (e) {
|
171
|
+
// console.error(e)
|
172
|
+
throw Error(e)
|
173
|
+
}
|
174
|
+
|
175
|
+
return computedDataMultiValue
|
176
|
+
}
|
@@ -1,12 +1,12 @@
|
|
1
|
-
import type { ContextObserverCallback } from '../../lib/core-types'
|
2
|
-
|
3
|
-
export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({ subject, observer }) => {
|
4
|
-
|
5
|
-
return {
|
6
|
-
fullParams$: observer.fullParams$,
|
7
|
-
fullChartParams$: observer.fullChartParams$,
|
8
|
-
fullDataFormatter$: observer.fullDataFormatter$,
|
9
|
-
computedData$: observer.computedData$,
|
10
|
-
layout$: observer.layout$,
|
11
|
-
}
|
12
|
-
}
|
1
|
+
import type { ContextObserverCallback } from '../../lib/core-types'
|
2
|
+
|
3
|
+
export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({ subject, observer }) => {
|
4
|
+
|
5
|
+
return {
|
6
|
+
fullParams$: observer.fullParams$,
|
7
|
+
fullChartParams$: observer.fullChartParams$,
|
8
|
+
fullDataFormatter$: observer.fullDataFormatter$,
|
9
|
+
computedData$: observer.computedData$,
|
10
|
+
layout$: observer.layout$,
|
11
|
+
}
|
12
|
+
}
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
|
2
|
-
|
3
|
-
export const dataFormatterValidator: DataFormatterValidator<'multiValue'> = (dataFormatter: DataFormatterTypeMap<'multiValue'>) => {
|
4
|
-
|
5
|
-
return {
|
6
|
-
status: 'success',
|
7
|
-
columnName: '',
|
8
|
-
expectToBe: ''
|
9
|
-
}
|
1
|
+
import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
|
2
|
+
|
3
|
+
export const dataFormatterValidator: DataFormatterValidator<'multiValue'> = (dataFormatter: DataFormatterTypeMap<'multiValue'>) => {
|
4
|
+
|
5
|
+
return {
|
6
|
+
status: 'success',
|
7
|
+
columnName: '',
|
8
|
+
expectToBe: ''
|
9
|
+
}
|
10
10
|
}
|