@orbcharts/core 3.0.4 → 3.0.6
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/dist/orbcharts-core.es.js +2328 -2226
- package/dist/orbcharts-core.umd.js +5 -5
- package/dist/src/series/seriesObservables.d.ts +18 -7
- package/package.json +2 -2
- package/src/base/createBaseChart.ts +18 -18
- package/src/defaults.ts +1 -0
- package/src/grid/contextObserverCallback.ts +8 -0
- package/src/grid/gridObservables.ts +11 -31
- package/src/multiGrid/contextObserverCallback.ts +36 -2
- package/src/multiGrid/multiGridObservables.ts +9 -44
- package/src/multiValue/multiValueObservables.ts +1 -355
- package/src/relationship/relationshipObservables.ts +1 -1
- package/src/series/contextObserverCallback.ts +36 -11
- package/src/series/seriesObservables.ts +103 -69
- package/src/tree/treeObservables.ts +3 -3
- package/src/utils/observables.ts +42 -27
@@ -18,6 +18,20 @@ import type {
|
|
18
18
|
Layout } from '../../lib/core-types'
|
19
19
|
import { calcContainerPosition } from '../utils/orbchartsUtils'
|
20
20
|
|
21
|
+
export const datumLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
|
22
|
+
const DatumLabels = new Set<string>()
|
23
|
+
return computedData$.pipe(
|
24
|
+
map(data => {
|
25
|
+
data.forEach(series => {
|
26
|
+
series.forEach(datum => {
|
27
|
+
DatumLabels.add(datum.label)
|
28
|
+
})
|
29
|
+
})
|
30
|
+
return Array.from(DatumLabels)
|
31
|
+
}),
|
32
|
+
)
|
33
|
+
}
|
34
|
+
|
21
35
|
export const separateSeriesObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
|
22
36
|
return fullDataFormatter$.pipe(
|
23
37
|
map(data => data.separateSeries),
|
@@ -25,6 +39,20 @@ export const separateSeriesObservable = ({ fullDataFormatter$ }: { fullDataForma
|
|
25
39
|
)
|
26
40
|
}
|
27
41
|
|
42
|
+
export const separateLabelObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
|
43
|
+
return fullDataFormatter$.pipe(
|
44
|
+
map(data => data.separateLabel),
|
45
|
+
distinctUntilChanged(),
|
46
|
+
)
|
47
|
+
}
|
48
|
+
|
49
|
+
export const sumSeriesObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
|
50
|
+
return fullDataFormatter$.pipe(
|
51
|
+
map(data => data.sumSeries),
|
52
|
+
distinctUntilChanged(),
|
53
|
+
)
|
54
|
+
}
|
55
|
+
|
28
56
|
export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
|
29
57
|
return computedData$.pipe(
|
30
58
|
map(data => {
|
@@ -35,7 +63,7 @@ export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Obser
|
|
35
63
|
})
|
36
64
|
}),
|
37
65
|
distinctUntilChanged((a, b) => {
|
38
|
-
return JSON.stringify(a)
|
66
|
+
return JSON.stringify(a) === JSON.stringify(b)
|
39
67
|
}),
|
40
68
|
)
|
41
69
|
}
|
@@ -50,24 +78,34 @@ export const seriesVisibleComputedDataObservable = ({ computedData$ }: { compute
|
|
50
78
|
)
|
51
79
|
}
|
52
80
|
|
53
|
-
export const seriesComputedSortedDataObservable = ({ computedData$,
|
81
|
+
export const seriesComputedSortedDataObservable = ({ computedData$, separateSeries$, separateLabel$, sumSeries$, datumLabels$ }: {
|
54
82
|
computedData$: Observable<ComputedDataTypeMap<'series'>>,
|
55
|
-
|
83
|
+
separateSeries$: Observable<boolean>,
|
84
|
+
separateLabel$: Observable<boolean>,
|
85
|
+
sumSeries$: Observable<boolean>,
|
86
|
+
datumLabels$: Observable<string[]>
|
56
87
|
}) => {
|
57
88
|
return combineLatest({
|
58
89
|
computedData: computedData$,
|
59
|
-
|
90
|
+
separateSeries: separateSeries$,
|
91
|
+
separateLabel: separateLabel$,
|
92
|
+
sumSeries: sumSeries$,
|
93
|
+
datumLabels: datumLabels$,
|
60
94
|
}).pipe(
|
61
95
|
switchMap(async (d) => d),
|
62
96
|
map(data => {
|
63
|
-
|
97
|
+
|
98
|
+
// sum series
|
99
|
+
const sumData: ComputedDatumSeries[][] = data.sumSeries == true
|
64
100
|
? data.computedData.map(d => {
|
65
101
|
return [
|
66
102
|
// 加總為一筆資料
|
67
103
|
d.reduce((acc, current) => {
|
68
104
|
if (acc == null) {
|
69
|
-
|
105
|
+
// * 取得第一筆資料
|
106
|
+
return current
|
70
107
|
}
|
108
|
+
// 加總 value
|
71
109
|
acc.value = acc.value + current.value
|
72
110
|
return acc
|
73
111
|
}, null)
|
@@ -75,102 +113,98 @@ export const seriesComputedSortedDataObservable = ({ computedData$, fullDataForm
|
|
75
113
|
})
|
76
114
|
: data.computedData
|
77
115
|
|
78
|
-
|
116
|
+
// separate series
|
117
|
+
const separateSeriesData: ComputedDatumSeries[][] = data.separateSeries == true
|
79
118
|
// 有拆分的話每個series為一組
|
80
119
|
? sumData
|
81
|
-
.map(series => {
|
82
|
-
return series.sort((a, b) => a.seq - b.seq)
|
83
|
-
})
|
84
120
|
// 無拆分的話所有資料為一組
|
85
|
-
: [
|
86
|
-
|
121
|
+
: [sumData.flat()]
|
122
|
+
|
123
|
+
// separate label
|
124
|
+
const separateLabelData: ComputedDatumSeries[][] = data.separateLabel == true
|
125
|
+
// 有拆分的話每個label為一組
|
126
|
+
? (() => {
|
127
|
+
// datumLabel 的 index 對應
|
128
|
+
const datumLabelIndexMap = data.datumLabels.reduce((acc, datumLabel, index) => {
|
129
|
+
acc[datumLabel] = index
|
130
|
+
return acc
|
131
|
+
}, {} as { [key: string]: number })
|
132
|
+
|
133
|
+
return separateSeriesData
|
134
|
+
.map(series => {
|
135
|
+
return series.reduce((acc, current) => {
|
136
|
+
const index = datumLabelIndexMap[current.label]
|
137
|
+
if (acc[index] == null) {
|
138
|
+
acc[index] = []
|
139
|
+
}
|
140
|
+
acc[index].push(current)
|
141
|
+
return acc
|
142
|
+
}, [] as ComputedDatumSeries[][])
|
143
|
+
})
|
87
144
|
.flat()
|
88
|
-
|
89
|
-
|
145
|
+
})()
|
146
|
+
// 無拆分
|
147
|
+
: separateSeriesData
|
148
|
+
|
149
|
+
return data.separateSeries == true && data.separateLabel == true
|
150
|
+
// 全部拆分時全部一起排序
|
151
|
+
? separateLabelData
|
152
|
+
.sort((a, b) => a[0].seq - b[0].seq)
|
153
|
+
// 依各個 container 排序
|
154
|
+
: separateLabelData
|
155
|
+
.map(series => {
|
156
|
+
return series.sort((a, b) => a.seq - b.seq)
|
157
|
+
})
|
90
158
|
})
|
91
159
|
)
|
92
160
|
}
|
93
161
|
|
94
162
|
|
95
163
|
// 所有container位置(對應series)
|
96
|
-
export const seriesContainerPositionObservable = ({
|
97
|
-
|
164
|
+
export const seriesContainerPositionObservable = ({ computedSortedData$, fullDataFormatter$, layout$ }: {
|
165
|
+
computedSortedData$: Observable<ComputedDatumSeries[][]>
|
98
166
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
|
99
167
|
layout$: Observable<Layout>
|
100
168
|
}): Observable<ContainerPosition[]> => {
|
101
169
|
|
102
170
|
const gridContainerPosition$ = combineLatest({
|
103
|
-
|
171
|
+
computedSortedData: computedSortedData$,
|
104
172
|
fullDataFormatter: fullDataFormatter$,
|
105
173
|
layout: layout$,
|
106
174
|
}).pipe(
|
107
175
|
switchMap(async (d) => d),
|
108
176
|
map(data => {
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
// const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
|
115
|
-
// const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
|
116
|
-
// const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
117
|
-
// return {
|
118
|
-
// slotIndex: seriesIndex,
|
119
|
-
// rowIndex,
|
120
|
-
// columnIndex,
|
121
|
-
// startX,
|
122
|
-
// startY,
|
123
|
-
// centerX,
|
124
|
-
// centerY,
|
125
|
-
// width,
|
126
|
-
// height,
|
127
|
-
// }
|
128
|
-
// })
|
129
|
-
} else {
|
130
|
-
// -- 無拆分 --
|
131
|
-
return calcContainerPosition(data.layout, data.fullDataFormatter.container, 1)
|
132
|
-
// const columnIndex = 0
|
133
|
-
// const rowIndex = 0
|
134
|
-
// return data.computedData.map((seriesData, seriesIndex) => {
|
135
|
-
// const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
136
|
-
// return {
|
137
|
-
// slotIndex: 0,
|
138
|
-
// rowIndex,
|
139
|
-
// columnIndex,
|
140
|
-
// startX,
|
141
|
-
// startY,
|
142
|
-
// centerX,
|
143
|
-
// centerY,
|
144
|
-
// width,
|
145
|
-
// height,
|
146
|
-
// }
|
147
|
-
// })
|
148
|
-
}
|
177
|
+
|
178
|
+
// 已分類資料的分類數量
|
179
|
+
const amount = data.computedSortedData.length
|
180
|
+
|
181
|
+
return calcContainerPosition(data.layout, data.fullDataFormatter.container, amount)
|
149
182
|
})
|
150
183
|
)
|
151
184
|
|
152
185
|
return gridContainerPosition$
|
153
186
|
}
|
154
187
|
|
155
|
-
export const
|
188
|
+
export const datumContainerPositionMapObservable = ({ seriesContainerPosition$, computedSortedData$ }: {
|
156
189
|
seriesContainerPosition$: Observable<ContainerPosition[]>
|
157
|
-
|
158
|
-
separateSeries$: Observable<boolean>
|
190
|
+
computedSortedData$: Observable<ComputedDatumSeries[][]>
|
159
191
|
}) => {
|
160
192
|
return combineLatest({
|
161
193
|
seriesContainerPosition: seriesContainerPosition$,
|
162
|
-
|
163
|
-
separateSeries: separateSeries$,
|
194
|
+
computedSortedData: computedSortedData$,
|
164
195
|
}).pipe(
|
165
196
|
switchMap(async (d) => d),
|
166
197
|
map(data => {
|
167
|
-
return
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
198
|
+
return new Map<string, ContainerPosition>(
|
199
|
+
data.computedSortedData
|
200
|
+
.map((series, seriesIndex) => {
|
201
|
+
return series.map(datum => {
|
202
|
+
const m: [string, ContainerPosition] = [datum.id, data.seriesContainerPosition[seriesIndex]]
|
203
|
+
return m
|
204
|
+
})
|
205
|
+
})
|
206
|
+
.flat()
|
207
|
+
)
|
174
208
|
})
|
175
209
|
)
|
176
210
|
}
|
@@ -42,7 +42,7 @@ export const nodeListObservable = ({ computedData$ }: { computedData$: Observabl
|
|
42
42
|
// const categoryLabels$ = fullDataFormatter$.pipe(
|
43
43
|
// map(d => d.categoryLabels),
|
44
44
|
// distinctUntilChanged((a, b) => {
|
45
|
-
// return JSON.stringify(a)
|
45
|
+
// return JSON.stringify(a) === JSON.stringify(b)
|
46
46
|
// }),
|
47
47
|
// )
|
48
48
|
|
@@ -72,7 +72,7 @@ export const nodeListObservable = ({ computedData$ }: { computedData$: Observabl
|
|
72
72
|
// return Array.from(CurrentLabelSet)
|
73
73
|
// }),
|
74
74
|
// distinctUntilChanged((a, b) => {
|
75
|
-
// return JSON.stringify(a)
|
75
|
+
// return JSON.stringify(a) === JSON.stringify(b)
|
76
76
|
// }),
|
77
77
|
// )
|
78
78
|
// }
|
@@ -83,7 +83,7 @@ export const categoryLabelsObservable = (CategoryDataMap$: Observable<Map<string
|
|
83
83
|
return Array.from(data.keys())
|
84
84
|
}),
|
85
85
|
distinctUntilChanged((a, b) => {
|
86
|
-
return JSON.stringify(a)
|
86
|
+
return JSON.stringify(a) === JSON.stringify(b)
|
87
87
|
}),
|
88
88
|
)
|
89
89
|
}
|
package/src/utils/observables.ts
CHANGED
@@ -67,46 +67,60 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
|
|
67
67
|
// 預設的highlight
|
68
68
|
const highlightDefault$: Observable<HighlightTargetValue> = fullChartParams$.pipe(
|
69
69
|
takeUntil(destroy$),
|
70
|
-
map(d =>
|
70
|
+
map(d => d.highlightDefault),
|
71
|
+
distinctUntilChanged(),
|
72
|
+
map(highlightDefault => {
|
71
73
|
return {
|
72
74
|
id: null,
|
73
75
|
label: null,
|
74
76
|
seriesLabel: null,
|
75
77
|
groupLabel: null,
|
76
78
|
categoryLabel: null,
|
77
|
-
highlightDefault
|
79
|
+
highlightDefault
|
78
80
|
} as HighlightTargetValue
|
79
81
|
}),
|
80
|
-
|
82
|
+
shareReplay(1)
|
81
83
|
)
|
82
84
|
|
83
|
-
|
84
|
-
const highlightMouseover$: Observable<HighlightTargetValue> = event$.pipe(
|
85
|
+
const highlightTarget$: Observable<HighlightTarget> = fullChartParams$.pipe(
|
85
86
|
takeUntil(destroy$),
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
87
|
+
map(d => d.highlightTarget),
|
88
|
+
distinctUntilChanged(),
|
89
|
+
shareReplay(1)
|
90
|
+
)
|
91
|
+
|
92
|
+
// 事件觸發的highlight
|
93
|
+
const highlightMouseover$: Observable<HighlightTargetValue> = highlightTarget$.pipe(
|
94
|
+
switchMap(highlightTarget => {
|
95
|
+
return event$.pipe(
|
96
|
+
takeUntil(destroy$),
|
97
|
+
// filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
|
98
|
+
filter(d => d.eventName === 'mouseover'),
|
99
|
+
// distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
|
100
|
+
map(_d => {
|
101
|
+
const d = _d as any
|
102
|
+
return d.datum
|
103
|
+
? {
|
104
|
+
id: d.datum.id,
|
105
|
+
label: null, // label有可能重覆所以不做判斷
|
106
|
+
seriesLabel: highlightTarget === 'series' ? d.datum.seriesLabel : null,
|
107
|
+
groupLabel: highlightTarget === 'group' ? d.datum.groupLabel : null,
|
108
|
+
categoryLabel: highlightTarget === 'category' ? d.datum.categoryLabel : null,
|
109
|
+
highlightDefault: null
|
110
|
+
} as HighlightTargetValue
|
111
|
+
: {
|
112
|
+
id: null,
|
113
|
+
label: null,
|
114
|
+
seriesLabel: null,
|
115
|
+
groupLabel: null,
|
116
|
+
categoryLabel: null,
|
117
|
+
highlightDefault: null
|
118
|
+
} as HighlightTargetValue
|
119
|
+
})
|
120
|
+
)
|
108
121
|
})
|
109
122
|
)
|
123
|
+
|
110
124
|
const highlightMouseout$ = event$.pipe(
|
111
125
|
takeUntil(destroy$),
|
112
126
|
filter(d => d.eventName === 'mouseout'),
|
@@ -164,6 +178,7 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
|
|
164
178
|
} else if (data.fullChartParams.highlightTarget === 'category') {
|
165
179
|
datumList = getCategoryIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.categoryLabel)
|
166
180
|
}
|
181
|
+
|
167
182
|
subscriber.next(datumList as D[])
|
168
183
|
})
|
169
184
|
|