@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.
@@ -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).length === JSON.stringify(b).length
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$, fullDataFormatter$ }: {
81
+ export const seriesComputedSortedDataObservable = ({ computedData$, separateSeries$, separateLabel$, sumSeries$, datumLabels$ }: {
54
82
  computedData$: Observable<ComputedDataTypeMap<'series'>>,
55
- fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
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
- fullDataFormatter: fullDataFormatter$
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
- const sumData: ComputedDatumSeries[][] = data.fullDataFormatter.sumSeries == true
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
- return current // 取得第一筆資料
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
- return data.fullDataFormatter.separateSeries == true
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
- sumData
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
- .sort((a, b) => a.seq - b.seq)
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 = ({ computedData$, fullDataFormatter$, layout$ }: {
97
- computedData$: Observable<ComputedDataTypeMap<'series'>>
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
- computedData: computedData$,
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
- if (data.fullDataFormatter.separateSeries) {
111
- // -- 依slotIndexes計算 --
112
- return calcContainerPosition(data.layout, data.fullDataFormatter.container, data.computedData.length)
113
- // return data.computedData.map((seriesData, seriesIndex) => {
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 seriesContainerPositionMapObservable = ({ seriesContainerPosition$, seriesLabels$, separateSeries$ }: {
188
+ export const datumContainerPositionMapObservable = ({ seriesContainerPosition$, computedSortedData$ }: {
156
189
  seriesContainerPosition$: Observable<ContainerPosition[]>
157
- seriesLabels$: Observable<string[]>
158
- separateSeries$: Observable<boolean>
190
+ computedSortedData$: Observable<ComputedDatumSeries[][]>
159
191
  }) => {
160
192
  return combineLatest({
161
193
  seriesContainerPosition: seriesContainerPosition$,
162
- seriesLabels: seriesLabels$,
163
- separateSeries: separateSeries$,
194
+ computedSortedData: computedSortedData$,
164
195
  }).pipe(
165
196
  switchMap(async (d) => d),
166
197
  map(data => {
167
- return data.separateSeries
168
- ? new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
169
- return [seriesLabel, data.seriesContainerPosition[seriesIndex] ?? data.seriesContainerPosition[0]]
170
- }))
171
- : new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
172
- return [seriesLabel, data.seriesContainerPosition[0]]
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).length === JSON.stringify(b).length
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).length === JSON.stringify(b).length
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).length === JSON.stringify(b).length
86
+ return JSON.stringify(a) === JSON.stringify(b)
87
87
  }),
88
88
  )
89
89
  }
@@ -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: d.highlightDefault
79
+ highlightDefault
78
80
  } as HighlightTargetValue
79
81
  }),
80
- distinctUntilChanged()
82
+ shareReplay(1)
81
83
  )
82
84
 
83
- // 事件觸發的highlight
84
- const highlightMouseover$: Observable<HighlightTargetValue> = event$.pipe(
85
+ const highlightTarget$: Observable<HighlightTarget> = fullChartParams$.pipe(
85
86
  takeUntil(destroy$),
86
- // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
87
- filter(d => d.eventName === 'mouseover'),
88
- // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
89
- map(_d => {
90
- const d = _d as any
91
- return d.datum
92
- ? {
93
- id: d.datum.id,
94
- label: d.datum.label,
95
- seriesLabel: d.datum.seriesLabel,
96
- groupLabel: d.datum.groupLabel,
97
- categoryLabel: d.datum.categoryLabel,
98
- highlightDefault: null
99
- } as HighlightTargetValue
100
- : {
101
- id: null,
102
- label: null,
103
- seriesLabel: null,
104
- groupLabel: null,
105
- categoryLabel: null,
106
- highlightDefault: null
107
- } as HighlightTargetValue
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