@orbcharts/core 3.0.0-beta.9 → 3.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.
Files changed (35) hide show
  1. package/dist/orbcharts-core.es.js +2779 -2398
  2. package/dist/orbcharts-core.umd.js +4 -4
  3. package/dist/src/defaults.d.ts +2 -1
  4. package/dist/src/utils/gridObservables.d.ts +8 -4
  5. package/dist/src/utils/index.d.ts +0 -3
  6. package/dist/src/utils/multiGridObservables.d.ts +3 -2
  7. package/dist/src/utils/multiValueObservables.d.ts +76 -29
  8. package/dist/src/utils/observables.d.ts +8 -1
  9. package/dist/src/utils/orbchartsUtils.d.ts +9 -9
  10. package/dist/src/utils/seriesObservables.d.ts +1 -1
  11. package/package.json +2 -2
  12. package/src/base/createBaseChart.ts +4 -3
  13. package/src/base/createBasePlugin.ts +5 -4
  14. package/src/base/validators/chartParamsValidator.ts +4 -4
  15. package/src/defaults.ts +54 -10
  16. package/src/grid/contextObserverCallback.ts +31 -9
  17. package/src/grid/dataFormatterValidator.ts +42 -23
  18. package/src/multiGrid/contextObserverCallback.ts +38 -7
  19. package/src/multiValue/computedDataFn.ts +4 -1
  20. package/src/multiValue/contextObserverCallback.ts +159 -43
  21. package/src/multiValue/dataFormatterValidator.ts +85 -5
  22. package/src/multiValue/dataValidator.ts +9 -6
  23. package/src/relationship/computedDataFn.ts +37 -22
  24. package/src/relationship/dataFormatterValidator.ts +10 -6
  25. package/src/relationship/dataValidator.ts +10 -6
  26. package/src/series/contextObserverCallback.ts +18 -11
  27. package/src/tree/dataValidator.ts +1 -1
  28. package/src/utils/gridObservables.ts +32 -10
  29. package/src/utils/index.ts +3 -3
  30. package/src/utils/multiGridObservables.ts +34 -25
  31. package/src/utils/multiValueObservables.ts +479 -97
  32. package/src/utils/observables.ts +77 -15
  33. package/src/utils/orbchartsUtils.ts +9 -9
  34. package/src/utils/seriesObservables.ts +4 -4
  35. package/src/utils/validator.ts +1 -1
@@ -11,32 +11,51 @@ export const dataFormatterValidator: DataFormatterValidator<'grid'> = (dataForma
11
11
  // },
12
12
  container: {
13
13
  toBeTypes: ['object']
14
+ },
15
+ seriesDirection: {
16
+ toBe: '"row" | "column"',
17
+ test: (value) => value === 'row' || value === 'column'
18
+ },
19
+ rowLabels: {
20
+ toBeTypes: ['string[]']
21
+ },
22
+ columnLabels: {
23
+ toBeTypes: ['string[]']
24
+ },
25
+ valueAxis: {
26
+ toBeTypes: ['object']
27
+ },
28
+ groupAxis: {
29
+ toBeTypes: ['object']
30
+ },
31
+ separateSeries: {
32
+ toBeTypes: ['boolean']
14
33
  }
15
34
  })
16
35
  // if (dataFormatter.grid) {
17
- const visibleFilterResult = validateColumns(dataFormatter, {
18
- seriesDirection: {
19
- toBe: '"row" | "column"',
20
- test: (value) => value === 'row' || value === 'column'
21
- },
22
- rowLabels: {
23
- toBeTypes: ['string[]']
24
- },
25
- columnLabels: {
26
- toBeTypes: ['string[]']
27
- },
28
- valueAxis: {
29
- toBeTypes: ['object']
30
- },
31
- groupAxis: {
32
- toBeTypes: ['object']
33
- },
34
- separateSeries: {
35
- toBeTypes: ['boolean']
36
- }
37
- })
38
- if (visibleFilterResult.status === 'error') {
39
- return visibleFilterResult
36
+ // const visibleFilterResult = validateColumns(dataFormatter, {
37
+ // seriesDirection: {
38
+ // toBe: '"row" | "column"',
39
+ // test: (value) => value === 'row' || value === 'column'
40
+ // },
41
+ // rowLabels: {
42
+ // toBeTypes: ['string[]']
43
+ // },
44
+ // columnLabels: {
45
+ // toBeTypes: ['string[]']
46
+ // },
47
+ // valueAxis: {
48
+ // toBeTypes: ['object']
49
+ // },
50
+ // groupAxis: {
51
+ // toBeTypes: ['object']
52
+ // },
53
+ // separateSeries: {
54
+ // toBeTypes: ['boolean']
55
+ // }
56
+ // })
57
+ if (result.status === 'error') {
58
+ return result
40
59
  }
41
60
  if (dataFormatter.valueAxis) {
42
61
  const valueAxisResult = validateColumns(dataFormatter.valueAxis, {
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  map,
3
3
  shareReplay } from 'rxjs'
4
- import type { ContextObserverCallback } from '../../lib/core-types'
4
+ import type { ContextObserverCallback, DataGridDatum } from '../../lib/core-types'
5
5
  import { multiGridEachDetailObservable, multiGridContainerObservable } from '../utils/multiGridObservables'
6
- import { textSizePxObservable } from '../utils/observables'
6
+ import { textSizePxObservable, containerSizeObservable, highlightObservable } from '../utils/observables'
7
+ // import { createMultiGridSeriesLabels } from '../utils/orbchartsUtils'
8
+ import { combineLatest } from 'rxjs/internal/observable/combineLatest'
7
9
 
8
10
  export const contextObserverCallback: ContextObserverCallback<'multiGrid'> = ({ subject, observer }) => {
9
11
 
@@ -11,21 +13,48 @@ export const contextObserverCallback: ContextObserverCallback<'multiGrid'> = ({
11
13
  shareReplay(1)
12
14
  )
13
15
 
14
- const multiGridEachDetail$ = multiGridEachDetailObservable({
15
- fullDataFormatter$: observer.fullDataFormatter$,
16
+ const multiGridContainerPosition$ = multiGridContainerObservable({
16
17
  computedData$: observer.computedData$,
18
+ fullDataFormatter$: observer.fullDataFormatter$,
17
19
  layout$: observer.layout$,
20
+ }).pipe(
21
+ shareReplay(1)
22
+ )
23
+
24
+ const containerSize$ = containerSizeObservable({
25
+ layout$: observer.layout$,
26
+ containerPosition$: multiGridContainerPosition$.pipe(
27
+ map(d => d.flat())
28
+ )
29
+ }).pipe(
30
+ shareReplay(1)
31
+ )
32
+
33
+ // highlight全部grid
34
+ const multiGridHighlight$ = highlightObservable({
35
+ datumList$: observer.computedData$.pipe(
36
+ map(d => d.flat().flat()),
37
+ shareReplay(1)
38
+ ),
18
39
  fullChartParams$: observer.fullChartParams$,
19
40
  event$: subject.event$
20
41
  }).pipe(
21
42
  shareReplay(1)
22
43
  )
23
44
 
24
- const multiGridContainerPosition$ = multiGridContainerObservable({
25
- computedData$: observer.computedData$,
45
+ const multiGridEachDetail$ = multiGridEachDetailObservable({
26
46
  fullDataFormatter$: observer.fullDataFormatter$,
47
+ computedData$: observer.computedData$,
27
48
  layout$: observer.layout$,
28
- })
49
+ fullChartParams$: observer.fullChartParams$,
50
+ event$: subject.event$,
51
+ containerSize$
52
+ }).pipe(
53
+ shareReplay(1)
54
+ )
55
+ // multiGridContainerPosition$.subscribe(d => {
56
+ // console.log('multiGridContainerPosition$', d)
57
+ // })
29
58
 
30
59
  return {
31
60
  fullParams$: observer.fullParams$,
@@ -34,6 +63,8 @@ export const contextObserverCallback: ContextObserverCallback<'multiGrid'> = ({
34
63
  computedData$: observer.computedData$,
35
64
  layout$: observer.layout$,
36
65
  textSizePx$,
66
+ containerSize$,
67
+ multiGridHighlight$,
37
68
  multiGridContainerPosition$,
38
69
  multiGridEachDetail$,
39
70
  // multiGridContainer$
@@ -87,10 +87,13 @@ export const computedDataFn: ComputedDataFn<'multiValue'> = (context) => {
87
87
  value: d.value,
88
88
  categoryIndex,
89
89
  categoryLabel: d.categoryLabel,
90
+ xValueIndex: dataFormatter.xAxis.valueIndex,
91
+ yValueIndex: dataFormatter.yAxis.valueIndex,
90
92
  // valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
91
93
  // axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
92
94
  visible: true, // 先給預設值
93
- color
95
+ color,
96
+ _visibleValue: d.value // 預設和value相同
94
97
  }
95
98
 
96
99
  computedDatum.visible = dataFormatter.visibleFilter(computedDatum, context)
@@ -1,22 +1,34 @@
1
1
  import { map, shareReplay, distinctUntilChanged } from 'rxjs'
2
+ import type { Observable } from 'rxjs'
2
3
  import type { ContextObserverCallback, ContextObserverTypeMap } from '../../lib/core-types'
3
4
  import {
4
5
  highlightObservable,
5
6
  categoryDataMapObservable,
6
- textSizePxObservable
7
+ textSizePxObservable,
8
+ containerSizeObservable
7
9
  } from '../utils/observables'
8
10
  import {
9
- multiValueComputedLayoutDataObservable,
11
+ computedXYDataObservable,
10
12
  // multiValueAxesTransformObservable,
11
13
  // multiValueAxesReverseTransformObservable,
12
- multiValueGraphicTransformObservable,
13
- multiValueGraphicReverseScaleObservable,
14
- multiValueCategoryLabelsObservable,
15
- multiValueVisibleComputedDataObservable,
16
- multiValueVisibleComputedLayoutDataObservable,
17
- multiValueContainerPositionObservable,
18
- minMaxXYObservable,
19
- filteredMinMaxXYDataObservable
14
+ graphicTransformObservable,
15
+ graphicReverseScaleObservable,
16
+ categoryLabelsObservable,
17
+ visibleComputedDataObservable,
18
+ visibleComputedSumDataObservable,
19
+ visibleComputedRankingByIndexDataObservable,
20
+ visibleComputedRankingBySumDataObservable,
21
+ visibleComputedXYDataObservable,
22
+ containerPositionObservable,
23
+ // containerSizeObservable,
24
+ xyMinMaxObservable,
25
+ filteredXYMinMaxDataObservable,
26
+ // visibleComputedRankingDataObservable,
27
+ // rankingAmountLimitObservable,
28
+ // rankingScaleObservable
29
+ xScaleObservable,
30
+ xSumScaleObservable,
31
+ yScaleObservable
20
32
  } from '../utils/multiValueObservables'
21
33
 
22
34
  export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({ subject, observer }) => {
@@ -31,11 +43,20 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
31
43
  shareReplay(1)
32
44
  )
33
45
 
34
- const multiValueContainerPosition$ = multiValueContainerPositionObservable({
46
+ const containerPosition$ = containerPositionObservable({
35
47
  computedData$: observer.computedData$,
36
48
  fullDataFormatter$: observer.fullDataFormatter$,
37
49
  layout$: observer.layout$,
38
- })
50
+ }).pipe(
51
+ shareReplay(1)
52
+ )
53
+
54
+ const containerSize$ = containerSizeObservable({
55
+ layout$: observer.layout$,
56
+ containerPosition$
57
+ }).pipe(
58
+ shareReplay(1)
59
+ )
39
60
 
40
61
  // const multiValueAxesSize$ = multiValueAxesSizeObservable({
41
62
  // fullDataFormatter$: observer.fullDataFormatter$,
@@ -44,13 +65,20 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
44
65
  // shareReplay(1)
45
66
  // )
46
67
 
68
+ // [xValueIndex, yValueIndex]
69
+ const xyValueIndex$: Observable<[number, number]> = observer.fullDataFormatter$.pipe(
70
+ map(d => [d.xAxis.valueIndex, d.yAxis.valueIndex] as [number, number]),
71
+ distinctUntilChanged((a, b) => a[0] === b[0] && a[1] === b[1]),
72
+ shareReplay(1)
73
+ )
74
+
47
75
  const datumList$ = observer.computedData$.pipe(
48
76
  map(d => d.flat().flat())
49
77
  ).pipe(
50
78
  shareReplay(1)
51
79
  )
52
80
 
53
- const multiValueHighlight$ = highlightObservable({
81
+ const highlight$ = highlightObservable({
54
82
  datumList$,
55
83
  fullChartParams$: observer.fullChartParams$,
56
84
  event$: subject.event$
@@ -58,10 +86,12 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
58
86
  shareReplay(1)
59
87
  )
60
88
 
61
- const categoryLabels$ = multiValueCategoryLabelsObservable({
89
+ const categoryLabels$ = categoryLabelsObservable({
62
90
  computedData$: observer.computedData$,
63
91
  fullDataFormatter$: observer.fullDataFormatter$,
64
- })
92
+ }).pipe(
93
+ shareReplay(1)
94
+ )
65
95
 
66
96
  const CategoryDataMap$ = categoryDataMapObservable({
67
97
  datumList$: datumList$
@@ -69,42 +99,91 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
69
99
  shareReplay(1)
70
100
  )
71
101
 
72
- const minMaxXY$ = minMaxXYObservable({
73
- computedData$: observer.computedData$
102
+ const xyMinMax$ = xyMinMaxObservable({
103
+ computedData$: observer.computedData$,
104
+ xyValueIndex$
74
105
  }).pipe(
75
106
  shareReplay(1)
76
107
  )
77
108
 
78
-
79
- const computedLayoutData$ = multiValueComputedLayoutDataObservable({
109
+ const visibleComputedData$ = visibleComputedDataObservable({
80
110
  computedData$: observer.computedData$,
81
- minMaxXY$,
82
- fullDataFormatter$: observer.fullDataFormatter$,
83
- layout$: observer.layout$,
84
111
  }).pipe(
85
112
  shareReplay(1)
86
113
  )
87
114
 
88
- const visibleComputedData$ = multiValueVisibleComputedDataObservable({
115
+ const visibleComputedSumData$ = visibleComputedSumDataObservable({
116
+ visibleComputedData$
117
+ }).pipe(
118
+ shareReplay(1)
119
+ )
120
+
121
+ // const valueIndex$ = observer.fullDataFormatter$.pipe(
122
+ // map(d => d.yAxis.valueIndex),
123
+ // distinctUntilChanged()
124
+ // )
125
+
126
+ const visibleComputedRankingByIndexData$ = visibleComputedRankingByIndexDataObservable({
127
+ xyValueIndex$, // * 依據 valueIndex 來取得 visibleComputedData
128
+ isCategorySeprate$,
129
+ visibleComputedData$
130
+ }).pipe(
131
+ shareReplay(1)
132
+ )
133
+
134
+ const visibleComputedRankingBySumData$ = visibleComputedRankingBySumDataObservable({
135
+ isCategorySeprate$,
136
+ visibleComputedSumData$
137
+ }).pipe(
138
+ shareReplay(1)
139
+ )
140
+
141
+ const computedXYData$ = computedXYDataObservable({
89
142
  computedData$: observer.computedData$,
143
+ xyMinMax$,
144
+ xyValueIndex$,
145
+ fullDataFormatter$: observer.fullDataFormatter$,
146
+ layout$: observer.layout$,
90
147
  }).pipe(
91
148
  shareReplay(1)
92
149
  )
93
150
 
94
- const visibleComputedLayoutData$ = multiValueVisibleComputedLayoutDataObservable({
95
- computedLayoutData$: computedLayoutData$,
151
+ const visibleComputedXYData$ = visibleComputedXYDataObservable({
152
+ computedXYData$: computedXYData$,
96
153
  }).pipe(
97
154
  shareReplay(1)
98
155
  )
99
156
 
100
- const filteredMinMaxXYData$ = filteredMinMaxXYDataObservable({
101
- visibleComputedLayoutData$: visibleComputedLayoutData$,
102
- minMaxXY$,
157
+ const filteredXYMinMaxData$ = filteredXYMinMaxDataObservable({
158
+ visibleComputedXYData$: visibleComputedXYData$,
159
+ xyMinMax$,
160
+ xyValueIndex$,
103
161
  fullDataFormatter$: observer.fullDataFormatter$,
104
162
  }).pipe(
105
163
  shareReplay(1)
106
164
  )
107
165
 
166
+ // const visibleComputedRankingData$ = visibleComputedRankingDataObservable({
167
+ // visibleComputedData$
168
+ // }).pipe(
169
+ // shareReplay(1)
170
+ // )
171
+
172
+ // const rankingAmountLimit$ = rankingAmountLimitObservable({
173
+ // layout$: observer.layout$,
174
+ // textSizePx$
175
+ // }).pipe(
176
+ // shareReplay(1)
177
+ // )
178
+
179
+ // const rankingScale$ = rankingScaleObservable({
180
+ // layout$: observer.layout$,
181
+ // visibleComputedRankingData$,
182
+ // rankingAmountLimit$
183
+ // }).pipe(
184
+ // shareReplay(1)
185
+ // )
186
+
108
187
  // const multiValueAxesTransform$ = multiValueAxesTransformObservable({
109
188
  // fullDataFormatter$: observer.fullDataFormatter$,
110
189
  // layout$: observer.layout$
@@ -118,21 +197,48 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
118
197
  // shareReplay(1)
119
198
  // )
120
199
 
121
- const multiValueGraphicTransform$ = multiValueGraphicTransformObservable({
122
- minMaxXY$,
123
- filteredMinMaxXYData$,
200
+ const graphicTransform$ = graphicTransformObservable({
201
+ xyMinMax$,
202
+ xyValueIndex$,
203
+ filteredXYMinMaxData$,
124
204
  fullDataFormatter$: observer.fullDataFormatter$,
125
205
  layout$: observer.layout$
126
206
  }).pipe(
127
207
  shareReplay(1)
128
208
  )
129
209
 
130
- const multiValueGraphicReverseScale$ = multiValueGraphicReverseScaleObservable({
131
- multiValueContainerPosition$: multiValueContainerPosition$,
210
+ const graphicReverseScale$ = graphicReverseScaleObservable({
211
+ containerPosition$: containerPosition$,
132
212
  // multiValueAxesTransform$: multiValueAxesTransform$,
133
- multiValueGraphicTransform$: multiValueGraphicTransform$,
134
- })
213
+ graphicTransform$: graphicTransform$,
214
+ }).pipe(
215
+ shareReplay(1)
216
+ )
217
+
218
+ const xScale$ = xScaleObservable({
219
+ visibleComputedSumData$,
220
+ fullDataFormatter$: observer.fullDataFormatter$,
221
+ filteredXYMinMaxData$,
222
+ containerSize$: containerSize$,
223
+ }).pipe(
224
+ shareReplay(1)
225
+ )
226
+
227
+ const xSumScale$ = xSumScaleObservable({
228
+ fullDataFormatter$: observer.fullDataFormatter$,
229
+ filteredXYMinMaxData$,
230
+ containerSize$: containerSize$,
231
+ }).pipe(
232
+ shareReplay(1)
233
+ )
135
234
 
235
+ const yScale$ = yScaleObservable({
236
+ fullDataFormatter$: observer.fullDataFormatter$,
237
+ filteredXYMinMaxData$,
238
+ containerSize$: containerSize$,
239
+ }).pipe(
240
+ shareReplay(1)
241
+ )
136
242
 
137
243
  return <ContextObserverTypeMap<'multiValue', any>>{
138
244
  fullParams$: observer.fullParams$,
@@ -142,19 +248,29 @@ export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({
142
248
  layout$: observer.layout$,
143
249
  textSizePx$,
144
250
  isCategorySeprate$,
145
- multiValueContainerPosition$,
251
+ containerPosition$,
252
+ containerSize$,
146
253
  // multiValueAxesSize$,
147
- multiValueHighlight$,
254
+ highlight$,
148
255
  categoryLabels$,
149
256
  CategoryDataMap$,
150
- minMaxXY$,
151
- computedLayoutData$,
257
+ xyMinMax$,
258
+ xyValueIndex$,
259
+ // computedXYData$,
152
260
  visibleComputedData$,
153
- visibleComputedLayoutData$,
154
- filteredMinMaxXYData$,
261
+ visibleComputedSumData$,
262
+ visibleComputedRankingByIndexData$,
263
+ visibleComputedRankingBySumData$,
264
+ visibleComputedXYData$,
265
+ filteredXYMinMaxData$,
266
+ // visibleComputedRankingData$,
267
+ // rankingScale$,
155
268
  // multiValueAxesTransform$,
156
269
  // multiValueAxesReverseTransform$,
157
- multiValueGraphicTransform$,
158
- multiValueGraphicReverseScale$,
270
+ graphicTransform$,
271
+ graphicReverseScale$,
272
+ xScale$,
273
+ xSumScale$,
274
+ yScale$
159
275
  }
160
276
  }
@@ -1,10 +1,90 @@
1
1
  import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
2
+ import { validateColumns } from '../utils/validator'
2
3
 
3
4
  export const dataFormatterValidator: DataFormatterValidator<'multiValue'> = (dataFormatter: DataFormatterTypeMap<'multiValue'>) => {
4
-
5
- return {
6
- status: 'success',
7
- columnName: '',
8
- expectToBe: ''
5
+ const result = validateColumns(dataFormatter, {
6
+ visibleFilter: {
7
+ toBeTypes: ['Function']
8
+ },
9
+ container: {
10
+ toBeTypes: ['object']
11
+ },
12
+ categoryLabels: {
13
+ toBeTypes: ['string[]']
14
+ },
15
+ valueLabels: {
16
+ toBeTypes: ['string[]']
17
+ },
18
+ xAxis: {
19
+ toBeTypes: ['object']
20
+ },
21
+ yAxis: {
22
+ toBeTypes: ['object']
23
+ },
24
+ separateCategory: {
25
+ toBeTypes: ['boolean']
26
+ }
27
+ })
28
+ if (result.status === 'error') {
29
+ return result
9
30
  }
31
+ if (dataFormatter.yAxis) {
32
+ const valueAxisResult = validateColumns(dataFormatter.yAxis, {
33
+ scaleDomain: {
34
+ toBe: '[number | "min" | "auto", number | "max" | "auto"]',
35
+ 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')
36
+ },
37
+ scaleRange: {
38
+ toBe: '[number, number]',
39
+ test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number'
40
+ },
41
+ label: {
42
+ toBeTypes: ['string']
43
+ },
44
+ valueIndex: {
45
+ toBeTypes: ['number']
46
+ }
47
+ })
48
+ if (valueAxisResult.status === 'error') {
49
+ return valueAxisResult
50
+ }
51
+ }
52
+ if (dataFormatter.xAxis) {
53
+ const groupAxisResult = validateColumns(dataFormatter.xAxis, {
54
+ scaleDomain: {
55
+ toBe: '[number | "min" | "auto", number | "max" | "auto"]',
56
+ 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')
57
+ },
58
+ scaleRange: {
59
+ toBe: '[number, number]',
60
+ test: (value) => Array.isArray(value) && value.length === 2 && typeof value[0] === 'number' && typeof value[1] === 'number'
61
+ },
62
+ label: {
63
+ toBeTypes: ['string']
64
+ },
65
+ valueIndex: {
66
+ toBeTypes: ['number']
67
+ }
68
+ })
69
+ if (groupAxisResult.status === 'error') {
70
+ return groupAxisResult
71
+ }
72
+ }
73
+ if (dataFormatter.container) {
74
+ const containerResult = validateColumns(dataFormatter.container, {
75
+ gap: {
76
+ toBeTypes: ['number']
77
+ },
78
+ rowAmount: {
79
+ toBeTypes: ['number']
80
+ },
81
+ columnAmount: {
82
+ toBeTypes: ['number']
83
+ }
84
+ })
85
+ if (containerResult.status === 'error') {
86
+ return containerResult
87
+ }
88
+ }
89
+ return result
10
90
  }
@@ -1,10 +1,13 @@
1
1
  import type { DataValidator, DataTypeMap } from '../../lib/core-types'
2
+ import { validateColumns } from '../utils/validator'
2
3
 
3
4
  export const dataValidator: DataValidator<'multiValue'> = (data: DataTypeMap<'multiValue'>) => {
4
-
5
- return {
6
- status: 'success',
7
- columnName: '',
8
- expectToBe: ''
9
- }
5
+ const result = validateColumns({ data }, {
6
+ data: {
7
+ toBe: '(DataMultiValueDatum | DataMultiValueValue[])[]',
8
+ // 畢免資料量過大檢查不完,不深度檢查
9
+ test: (value) => Array.isArray(value)
10
+ }
11
+ })
12
+ return result
10
13
  }
@@ -106,30 +106,45 @@ export const computedDataFn: ComputedDataFn<'relationship'> = (context) => {
106
106
  // })()
107
107
 
108
108
  // -- edges --
109
- computedEdges = edges.map((edge, i) => {
110
- const categoryLabel = edge.categoryLabel ?? defaultCategoryLabel
111
- const startNode = NodesMap.get(edge.start)
112
- const endNode = NodesMap.get(edge.end)
109
+ computedEdges = edges
110
+ .map((edge, i) => {
111
+ const startNode = NodesMap.get(edge.start)
112
+ const endNode = NodesMap.get(edge.end)
113
+ return {
114
+ edge,
115
+ startNode,
116
+ endNode
117
+ }
118
+ })
119
+ .filter(({ edge }) => {
120
+ const startNode = NodesMap.get(edge.start)
121
+ const endNode = NodesMap.get(edge.end)
122
+ return startNode != null && endNode != null
123
+ })
124
+ .map(({ edge, startNode, endNode }, i) => {
125
+ const categoryLabel = edge.categoryLabel ?? defaultCategoryLabel
126
+ // const startNode = NodesMap.get(edge.start)
127
+ // const endNode = NodesMap.get(edge.end)
113
128
 
114
- const computedEdge: ComputedEdge = {
115
- id: edge.id,
116
- index: i,
117
- label: edge.label ?? '',
118
- description: edge.description ?? '',
119
- data: edge.data ?? {},
120
- value: edge.value ?? 0,
121
- categoryIndex: CategoryIndexMap.get(categoryLabel),
122
- categoryLabel,
123
- color: seriesColorPredicate(i, chartParams),
124
- startNode,
125
- // startNodeId: edge.start,
126
- endNode,
127
- // endNodeId: edge.end,
128
- visible: startNode.visible && endNode.visible
129
- }
129
+ const computedEdge: ComputedEdge = {
130
+ id: edge.id,
131
+ index: i,
132
+ label: edge.label ?? '',
133
+ description: edge.description ?? '',
134
+ data: edge.data ?? {},
135
+ value: edge.value ?? 0,
136
+ categoryIndex: CategoryIndexMap.get(categoryLabel),
137
+ categoryLabel,
138
+ color: seriesColorPredicate(i, chartParams),
139
+ startNode,
140
+ // startNodeId: edge.start,
141
+ endNode,
142
+ // endNodeId: edge.end,
143
+ visible: startNode.visible && endNode.visible
144
+ }
130
145
 
131
- return computedEdge
132
- })
146
+ return computedEdge
147
+ })
133
148
 
134
149
 
135
150
  } catch (e) {
@@ -1,10 +1,14 @@
1
1
  import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
2
+ import { validateColumns } from '../utils/validator'
2
3
 
3
4
  export const dataFormatterValidator: DataFormatterValidator<'relationship'> = (dataFormatter: DataFormatterTypeMap<'relationship'>) => {
4
-
5
- return {
6
- status: 'success',
7
- columnName: '',
8
- expectToBe: ''
9
- }
5
+ const result = validateColumns(dataFormatter, {
6
+ visibleFilter: {
7
+ toBeTypes: ['Function']
8
+ },
9
+ categoryLabels: {
10
+ toBeTypes: ['string[]']
11
+ }
12
+ })
13
+ return result
10
14
  }