@orbcharts/core 3.0.0-alpha.42 → 3.0.0-alpha.43

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +1905 -1896
  3. package/dist/orbcharts-core.umd.js +2 -2
  4. package/dist/src/defaults.d.ts +4 -3
  5. package/dist/src/grid/computeGridData.d.ts +4 -11
  6. package/dist/src/grid/gridObservables.d.ts +15 -18
  7. package/dist/src/multiGrid/multiGridObservables.d.ts +4 -11
  8. package/dist/src/series/seriesObservables.d.ts +26 -1
  9. package/dist/src/types/ComputedData.d.ts +1 -0
  10. package/dist/src/types/ComputedDataGrid.d.ts +0 -3
  11. package/dist/src/types/ComputedDataSeries.d.ts +1 -2
  12. package/dist/src/types/ContextObserverGrid.d.ts +11 -4
  13. package/dist/src/types/ContextObserverMultiGrid.d.ts +8 -3
  14. package/dist/src/types/ContextObserverSeries.d.ts +18 -0
  15. package/dist/src/types/DataFormatter.d.ts +8 -5
  16. package/dist/src/types/DataFormatterGrid.d.ts +13 -16
  17. package/dist/src/types/DataFormatterMultiGrid.d.ts +6 -3
  18. package/dist/src/types/DataFormatterMultiValue.d.ts +3 -0
  19. package/dist/src/types/DataFormatterRelationship.d.ts +3 -0
  20. package/dist/src/types/DataFormatterSeries.d.ts +10 -3
  21. package/dist/src/utils/orbchartsUtils.d.ts +14 -13
  22. package/package.json +41 -41
  23. package/src/AbstractChart.ts +48 -48
  24. package/src/GridChart.ts +20 -20
  25. package/src/MultiGridChart.ts +20 -20
  26. package/src/MultiValueChart.ts +20 -20
  27. package/src/RelationshipChart.ts +20 -20
  28. package/src/SeriesChart.ts +20 -20
  29. package/src/TreeChart.ts +20 -20
  30. package/src/base/createBaseChart.ts +367 -367
  31. package/src/base/createBasePlugin.ts +89 -89
  32. package/src/defaults.ts +220 -248
  33. package/src/defineGridPlugin.ts +3 -3
  34. package/src/defineMultiGridPlugin.ts +3 -3
  35. package/src/defineMultiValuePlugin.ts +3 -3
  36. package/src/defineNoneDataPlugin.ts +4 -4
  37. package/src/defineRelationshipPlugin.ts +3 -3
  38. package/src/defineSeriesPlugin.ts +3 -3
  39. package/src/defineTreePlugin.ts +3 -3
  40. package/src/grid/computeGridData.ts +134 -205
  41. package/src/grid/createGridContextObserver.ts +147 -130
  42. package/src/grid/gridObservables.ts +573 -486
  43. package/src/index.ts +21 -21
  44. package/src/multiGrid/computeMultiGridData.ts +130 -173
  45. package/src/multiGrid/createMultiGridContextObserver.ts +40 -40
  46. package/src/multiGrid/multiGridObservables.ts +350 -285
  47. package/src/multiValue/computeMultiValueData.ts +143 -136
  48. package/src/multiValue/createMultiValueContextObserver.ts +12 -12
  49. package/src/relationship/computeRelationshipData.ts +118 -106
  50. package/src/relationship/createRelationshipContextObserver.ts +12 -12
  51. package/src/series/computeSeriesData.ts +90 -153
  52. package/src/series/createSeriesContextObserver.ts +93 -38
  53. package/src/series/seriesObservables.ts +176 -24
  54. package/src/tree/computeTreeData.ts +131 -128
  55. package/src/tree/createTreeContextObserver.ts +61 -61
  56. package/src/tree/treeObservables.ts +94 -94
  57. package/src/types/Chart.ts +48 -48
  58. package/src/types/ChartParams.ts +51 -51
  59. package/src/types/ComputedData.ts +83 -82
  60. package/src/types/ComputedDataGrid.ts +13 -13
  61. package/src/types/ComputedDataMultiGrid.ts +2 -2
  62. package/src/types/ComputedDataMultiValue.ts +9 -9
  63. package/src/types/ComputedDataRelationship.ts +19 -19
  64. package/src/types/ComputedDataSeries.ts +8 -8
  65. package/src/types/ComputedDataTree.ts +19 -19
  66. package/src/types/ContextObserver.ts +38 -38
  67. package/src/types/ContextObserverGrid.ts +41 -33
  68. package/src/types/ContextObserverMultiGrid.ts +16 -28
  69. package/src/types/ContextObserverMultiValue.ts +4 -4
  70. package/src/types/ContextObserverRelationship.ts +4 -4
  71. package/src/types/ContextObserverSeries.ts +29 -9
  72. package/src/types/ContextObserverTree.ts +11 -11
  73. package/src/types/ContextSubject.ts +18 -18
  74. package/src/types/Data.ts +45 -45
  75. package/src/types/DataFormatter.ts +74 -95
  76. package/src/types/DataFormatterGrid.ts +67 -55
  77. package/src/types/DataFormatterMultiGrid.ts +44 -42
  78. package/src/types/DataFormatterMultiValue.ts +23 -20
  79. package/src/types/DataFormatterRelationship.ts +25 -22
  80. package/src/types/DataFormatterSeries.ts +20 -30
  81. package/src/types/DataFormatterTree.ts +12 -12
  82. package/src/types/DataGrid.ts +11 -11
  83. package/src/types/DataMultiGrid.ts +6 -6
  84. package/src/types/DataMultiValue.ts +12 -12
  85. package/src/types/DataRelationship.ts +27 -27
  86. package/src/types/DataSeries.ts +11 -11
  87. package/src/types/DataTree.ts +20 -20
  88. package/src/types/Event.ts +153 -153
  89. package/src/types/Layout.ts +11 -11
  90. package/src/types/Padding.ts +5 -5
  91. package/src/types/Plugin.ts +60 -60
  92. package/src/types/TransformData.ts +7 -7
  93. package/src/types/index.ts +37 -37
  94. package/src/utils/commonUtils.ts +50 -50
  95. package/src/utils/d3Utils.ts +89 -89
  96. package/src/utils/index.ts +4 -4
  97. package/src/utils/observables.ts +201 -201
  98. package/src/utils/orbchartsUtils.ts +349 -253
  99. package/tsconfig.json +13 -13
  100. package/vite.config.js +44 -44
@@ -1,153 +1,90 @@
1
- import type { DataSeries, DataSeriesDatum } from '../types/DataSeries'
2
- import type { ComputedDataFn } from '../types/ComputedData'
3
- import type { ComputedDataSeries, ComputedDatumSeries } from '../types/ComputedDataSeries'
4
- import { formatValueToLabel, createDefaultDatumId, createDefaultSeriesLabel, seriesColorPredicate } from '../utils/orbchartsUtils'
5
-
6
- interface SortValue {
7
- rowIndex: number
8
- columnIndex: number
9
- index: number
10
- datum: number | DataSeriesDatum
11
- }
12
-
13
- type GetSortedIndex = (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => number
14
-
15
- function createSortedIndexMap (data: DataSeries, sort: (a: number | DataSeriesDatum, b: number | DataSeriesDatum) => number): Map<string, number> {
16
-
17
- const SortedIndexMap: Map<string, number> = new Map() // Map<[rowIndex, columnIndex], sortedIndex>
18
-
19
- let _data = Object.assign([], data) as DataSeries
20
- // 建立排序所需資料的物件
21
- let sortValueData: SortValue[] = []
22
- _data.forEach((d, i) => {
23
- if (Array.isArray(d)) {
24
- d.forEach((_d, _i) => {
25
- sortValueData.push({
26
- rowIndex: i,
27
- columnIndex: _i,
28
- index: -1,
29
- datum: _d
30
- })
31
- })
32
- } else {
33
- sortValueData.push({
34
- rowIndex: i,
35
- columnIndex: 0,
36
- index: -1,
37
- datum: d
38
- })
39
- }
40
- })
41
- // 排序
42
- sortValueData.sort((a, b) => sort(a.datum, b.datum))
43
- // 取得排序後的index
44
- sortValueData = sortValueData.map((d, i) => {
45
- return {
46
- ...d,
47
- index: i
48
- }
49
- })
50
- // 建立SortedIndexMap
51
- sortValueData.forEach(d => {
52
- SortedIndexMap.set(String([d.rowIndex, d.columnIndex]), d.index)
53
- })
54
-
55
- return SortedIndexMap
56
- }
57
-
58
- export const computeSeriesData: ComputedDataFn<'series'> = (context) => {
59
- const { data = [], dataFormatter, chartParams } = context
60
- if (!data.length) {
61
- return []
62
- }
63
-
64
- const computedDataSeries: ComputedDatumSeries[] = []
65
-
66
- try {
67
- // 取得排序後的索引
68
- const getSortedIndex: GetSortedIndex = ((hasSort: boolean) => {
69
- if (hasSort) {
70
- // 資料索引對應排序後的索引 Map<[rowIndex, columnIndex], sortedIndex>
71
- const SortedIndexMap: Map<string, number> = createSortedIndexMap(data, dataFormatter.sort)
72
- return (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => {
73
- return SortedIndexMap.get(String([rowIndex, columnIndex]))
74
- }
75
- } else {
76
- return (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => {
77
- return computedDataSeries.length
78
- }
79
- }
80
- })(dataFormatter.sort != null)
81
-
82
- // 資料索引對應排序後的索引 Map<[rowIndex, columnIndex], sortedIndex>
83
- // let SortedIndexMap: Map<string, number> = new Map()
84
- // if (dataFormatter.sort) {
85
- // SortedIndexMap = createSortedIndexMap(data, dataFormatter.sort)
86
- // }
87
-
88
- const createComputedDatumSeries = (detailData: number | DataSeriesDatum, rowIndex: number, columnIndex: number, currentIndex: number, sortedIndex: number): ComputedDatumSeries => {
89
- const defaultId = createDefaultDatumId(dataFormatter.type, rowIndex, columnIndex)
90
- // const seriesLabel = dataFormatter.mapSeries(detailData, rowIndex, columnIndex, context)
91
- const seriesLabel = dataFormatter.seriesLabels[rowIndex] || createDefaultSeriesLabel('series', rowIndex)
92
- // const color = dataFormatter.colorsPredicate(detailData, rowIndex, columnIndex, context)
93
- const color = seriesColorPredicate(rowIndex, chartParams)
94
- const visible = dataFormatter.visibleFilter(detailData, rowIndex, columnIndex, context)
95
- if (typeof detailData === 'number') {
96
- return {
97
- id: defaultId,
98
- index: currentIndex,
99
- sortedIndex,
100
- label: defaultId,
101
- description: '',
102
- // tooltipContent: dataFormatter.tooltipContentFormat(detailData, rowIndex, columnIndex, context),
103
- data: {},
104
- value: detailData,
105
- // valueLabel: formatValueToLabel(detailData, dataFormatter.valueFormat),
106
- seriesIndex: rowIndex,
107
- seriesLabel,
108
- color,
109
- visible
110
- }
111
- } else {
112
- return {
113
- id: detailData.id ? detailData.id : defaultId,
114
- index: currentIndex,
115
- sortedIndex,
116
- label: detailData.label ? detailData.label : defaultId,
117
- description: detailData.description,
118
- // tooltipContent: detailData.tooltipContent ? detailData.tooltipContent : dataFormatter.tooltipContentFormat(detailData, rowIndex, columnIndex, context),
119
- data: detailData.data ?? {},
120
- value: detailData.value,
121
- // valueLabel: formatValueToLabel(detailData.value, dataFormatter.valueFormat),
122
- seriesIndex: rowIndex,
123
- seriesLabel,
124
- color,
125
- visible
126
- }
127
- }
128
- }
129
-
130
- data.forEach((mainData, rowIndex) => {
131
- if (Array.isArray(mainData)) {
132
- mainData.forEach((detailData, columnIndex) => {
133
- const sortedIndex = getSortedIndex(computedDataSeries, rowIndex, columnIndex)
134
- const datum = createComputedDatumSeries(detailData, rowIndex, columnIndex, computedDataSeries.length, sortedIndex)
135
- computedDataSeries.push(datum)
136
- })
137
- } else {
138
- const sortedIndex = getSortedIndex(computedDataSeries, rowIndex, 0)
139
- const datum = createComputedDatumSeries(mainData, rowIndex, 0, computedDataSeries.length, sortedIndex) // 只有一維陣列所以columnIndex為0
140
- computedDataSeries.push(datum)
141
- }
142
- })
143
-
144
- // if (dataFormatter.sort != null) {
145
- // computedDataSeries.sort((a, b) => a.sortedIndex - b.sortedIndex)
146
- // }
147
- } catch (e) {
148
- // console.error(e)
149
- throw Error(e)
150
- }
151
-
152
- return computedDataSeries
153
- }
1
+ import type { DataSeries, DataSeriesDatum } from '../types/DataSeries'
2
+ import type { ComputedDataFn } from '../types/ComputedData'
3
+ import type { ComputedDatumSeries } from '../types/ComputedDataSeries'
4
+ import { formatValueToLabel, createDefaultDatumId, createDefaultSeriesLabel, seriesColorPredicate } from '../utils/orbchartsUtils'
5
+
6
+ export const computeSeriesData: ComputedDataFn<'series'> = (context) => {
7
+ const { data = [], dataFormatter, chartParams } = context
8
+ if (!data.length) {
9
+ return []
10
+ }
11
+
12
+ let computedDataSeries: ComputedDatumSeries[][] = []
13
+
14
+ try {
15
+
16
+ const createComputedDatumSeries = (seriesData: number | DataSeriesDatum, seriesIndex: number, itemIndex: number, currentIndex: number): ComputedDatumSeries => {
17
+ const defaultId = createDefaultDatumId(dataFormatter.type, seriesIndex, itemIndex)
18
+ const seriesLabel = dataFormatter.seriesLabels[seriesIndex] || createDefaultSeriesLabel('series', seriesIndex)
19
+ const color = seriesColorPredicate(seriesIndex, chartParams)
20
+ if (typeof seriesData === 'number') {
21
+ return {
22
+ id: defaultId,
23
+ index: currentIndex,
24
+ seq: 0, // 先給預設值
25
+ label: defaultId,
26
+ description: '',
27
+ data: {},
28
+ value: seriesData,
29
+ seriesIndex: seriesIndex,
30
+ seriesLabel,
31
+ color,
32
+ visible: true // 先給預設值
33
+ }
34
+ } else {
35
+ return {
36
+ id: seriesData.id ? seriesData.id : defaultId,
37
+ index: currentIndex,
38
+ seq: 0, // 先給預設值
39
+ label: seriesData.label ? seriesData.label : defaultId,
40
+ description: seriesData.description,
41
+ data: seriesData.data ?? {},
42
+ value: seriesData.value,
43
+ seriesIndex: seriesIndex,
44
+ seriesLabel,
45
+ color,
46
+ visible: true // 先給預設值
47
+ }
48
+ }
49
+ }
50
+
51
+ computedDataSeries = data
52
+ .map((seriesData, seriesIndex) => {
53
+ if (Array.isArray(seriesData)) {
54
+ return seriesData.map((item, itemIndex) =>
55
+ createComputedDatumSeries(item, seriesIndex, itemIndex, computedDataSeries.length + itemIndex)
56
+ )
57
+ } else {
58
+ return createComputedDatumSeries(seriesData, seriesIndex, 0, computedDataSeries.length)
59
+ }
60
+ })
61
+ // 攤為一維陣列
62
+ .flat()
63
+ // 排序後給 seq
64
+ .sort(dataFormatter.sort ?? undefined)
65
+ .map((datum, index) => {
66
+ datum.seq = index
67
+ return datum
68
+ })
69
+ .map(datum => {
70
+ datum.visible = dataFormatter.visibleFilter(datum, context)
71
+ return datum
72
+ })
73
+ // 恢復原排序
74
+ .sort((a, b) => a.index - b.index)
75
+ // 依seriesIndex分組(二維陣列)
76
+ .reduce((acc, datum) => {
77
+ if (!acc[datum.seriesIndex]) {
78
+ acc[datum.seriesIndex] = []
79
+ }
80
+ acc[datum.seriesIndex].push(datum)
81
+ return acc
82
+ }, [])
83
+
84
+ } catch (e) {
85
+ // console.error(e)
86
+ throw Error(e)
87
+ }
88
+
89
+ return computedDataSeries
90
+ }
@@ -1,38 +1,93 @@
1
- import { shareReplay } from 'rxjs'
2
- import type { ContextObserverFn } from '../types'
3
- import {
4
- seriesDataMapObservable,
5
- groupDataMapObservable } from '../utils/observables'
6
- import { highlightObservable, textSizePxObservable } from '../utils/observables'
7
-
8
- export const createSeriesContextObserver: ContextObserverFn<'series'> = ({ subject, observer }) => {
9
-
10
- const textSizePx$ = textSizePxObservable(observer.fullChartParams$).pipe(
11
- shareReplay(1)
12
- )
13
-
14
- const seriesHighlight$ = highlightObservable({
15
- datumList$: observer.computedData$,
16
- fullChartParams$: observer.fullChartParams$,
17
- event$: subject.event$
18
- }).pipe(
19
- shareReplay(1)
20
- )
21
-
22
- const SeriesDataMap$ = seriesDataMapObservable({
23
- datumList$: observer.computedData$
24
- }).pipe(
25
- shareReplay(1)
26
- )
27
-
28
- return {
29
- fullParams$: observer.fullParams$,
30
- fullChartParams$: observer.fullChartParams$,
31
- fullDataFormatter$: observer.fullDataFormatter$,
32
- computedData$: observer.computedData$,
33
- layout$: observer.layout$,
34
- textSizePx$,
35
- seriesHighlight$,
36
- SeriesDataMap$
37
- }
38
- }
1
+ import { map, shareReplay } from 'rxjs'
2
+ import type { ContextObserverFn } from '../types'
3
+ import {
4
+ seriesDataMapObservable,
5
+ groupDataMapObservable } from '../utils/observables'
6
+ import { highlightObservable, textSizePxObservable } from '../utils/observables'
7
+
8
+ import { seriesSeparateObservable, visibleComputedDataObservable, computedLayoutDataObservable, seriesLabelsObservable, seriesContainerPositionObservable, seriesContainerPositionMapObservable } from './seriesObservables'
9
+
10
+ export const createSeriesContextObserver: ContextObserverFn<'series'> = ({ subject, observer }) => {
11
+
12
+ const textSizePx$ = textSizePxObservable(observer.fullChartParams$).pipe(
13
+ shareReplay(1)
14
+ )
15
+
16
+ const seriesSeparate$ = seriesSeparateObservable({
17
+ fullDataFormatter$: observer.fullDataFormatter$
18
+ })
19
+
20
+ const visibleComputedData$ = visibleComputedDataObservable({
21
+ computedData$: observer.computedData$,
22
+ })
23
+
24
+ const computedLayoutData$ = computedLayoutDataObservable({
25
+ computedData$: observer.computedData$,
26
+ fullDataFormatter$: observer.fullDataFormatter$
27
+ }).pipe(
28
+ shareReplay(1)
29
+ )
30
+
31
+ const visibleComputedLayoutData$ = visibleComputedDataObservable({
32
+ computedData$: computedLayoutData$,
33
+ })
34
+
35
+ const datumList$ = observer.computedData$.pipe(
36
+ map(d => d.flat())
37
+ ).pipe(
38
+ shareReplay(1)
39
+ )
40
+
41
+ const seriesHighlight$ = highlightObservable({
42
+ datumList$,
43
+ fullChartParams$: observer.fullChartParams$,
44
+ event$: subject.event$
45
+ }).pipe(
46
+ shareReplay(1)
47
+ )
48
+
49
+ const seriesLabels$ = seriesLabelsObservable({
50
+ computedData$: observer.computedData$,
51
+ })
52
+
53
+
54
+ const SeriesDataMap$ = seriesDataMapObservable({
55
+ datumList$
56
+ }).pipe(
57
+ shareReplay(1)
58
+ )
59
+
60
+ const seriesContainerPosition$ = seriesContainerPositionObservable({
61
+ computedData$: observer.computedData$,
62
+ fullDataFormatter$: observer.fullDataFormatter$,
63
+ layout$: observer.layout$,
64
+ }).pipe(
65
+ shareReplay(1)
66
+ )
67
+
68
+ const SeriesContainerPositionMap$ = seriesContainerPositionMapObservable({
69
+ seriesContainerPosition$: seriesContainerPosition$,
70
+ seriesLabels$: seriesLabels$,
71
+ seriesSeparate$: seriesSeparate$,
72
+ }).pipe(
73
+ shareReplay(1)
74
+ )
75
+
76
+ return {
77
+ fullParams$: observer.fullParams$,
78
+ fullChartParams$: observer.fullChartParams$,
79
+ fullDataFormatter$: observer.fullDataFormatter$,
80
+ computedData$: observer.computedData$,
81
+ layout$: observer.layout$,
82
+ textSizePx$,
83
+ visibleComputedData$,
84
+ visibleComputedLayoutData$,
85
+ seriesSeparate$,
86
+ computedLayoutData$,
87
+ seriesHighlight$,
88
+ seriesLabels$,
89
+ SeriesDataMap$,
90
+ seriesContainerPosition$,
91
+ SeriesContainerPositionMap$,
92
+ }
93
+ }
@@ -1,24 +1,176 @@
1
- import {
2
- combineLatest,
3
- distinctUntilChanged,
4
- filter,
5
- map,
6
- merge,
7
- takeUntil,
8
- shareReplay,
9
- switchMap,
10
- Subject,
11
- Observable } from 'rxjs'
12
- import type {
13
- ChartParams,
14
- ComputedDatumSeries,
15
- ComputedDataTypeMap } from '../types'
16
- import { highlightObservable } from '../utils/observables'
17
-
18
- // export const seriesHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
19
- // computedData$: Observable<ComputedDataTypeMap<'series'>>
20
- // fullChartParams$: Observable<ChartParams>
21
- // event$: Subject<any>
22
- // }): Observable<string[]> => {
23
- // return highlightObservable ({ datumList$: computedData$, fullChartParams$, event$ })
24
- // }
1
+ import {
2
+ combineLatest,
3
+ distinctUntilChanged,
4
+ filter,
5
+ map,
6
+ merge,
7
+ takeUntil,
8
+ shareReplay,
9
+ switchMap,
10
+ Subject,
11
+ Observable } from 'rxjs'
12
+ import type {
13
+ ChartParams,
14
+ ComputedDatumSeries,
15
+ ComputedDataTypeMap,
16
+ DataFormatterTypeMap,
17
+ SeriesContainerPosition,
18
+ Layout } from '../types'
19
+ import { calcSeriesContainerLayout } from '../utils/orbchartsUtils'
20
+
21
+ export const seriesSeparateObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
22
+ return fullDataFormatter$.pipe(
23
+ map(data => data.separateSeries),
24
+ distinctUntilChanged(),
25
+ )
26
+ }
27
+
28
+ export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
29
+ return computedData$.pipe(
30
+ map(data => {
31
+ return data
32
+ .filter(series => series.length)
33
+ .map(series => {
34
+ return series[0].seriesLabel
35
+ })
36
+ }),
37
+ distinctUntilChanged((a, b) => {
38
+ return JSON.stringify(a).length === JSON.stringify(b).length
39
+ }),
40
+ )
41
+ }
42
+
43
+ export const visibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
44
+ return computedData$.pipe(
45
+ map(data => {
46
+ return data.map(series => {
47
+ return series.filter(datum => datum.visible != false)
48
+ })
49
+ })
50
+ )
51
+ }
52
+
53
+ export const computedLayoutDataObservable = ({ computedData$, fullDataFormatter$ }: {
54
+ computedData$: Observable<ComputedDataTypeMap<'series'>>,
55
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
56
+ }) => {
57
+ return combineLatest({
58
+ computedData: computedData$,
59
+ fullDataFormatter: fullDataFormatter$
60
+ }).pipe(
61
+ switchMap(async (d) => d),
62
+ map(data => {
63
+ const sumData: ComputedDatumSeries[][] = data.fullDataFormatter.sumSeries == true
64
+ ? data.computedData.map(d => {
65
+ return [
66
+ // 加總為一筆資料
67
+ d.reduce((acc, current) => {
68
+ if (acc == null) {
69
+ return current // 取得第一筆資料
70
+ }
71
+ acc.value = acc.value + current.value
72
+ return acc
73
+ }, null)
74
+ ]
75
+ })
76
+ : data.computedData
77
+
78
+ return data.fullDataFormatter.separateSeries == true
79
+ // 有拆分的話每個series為一組
80
+ ? sumData
81
+ .map(series => {
82
+ return series.sort((a, b) => a.seq - b.seq)
83
+ })
84
+ // 無拆分的話所有資料為一組
85
+ : [
86
+ sumData
87
+ .flat()
88
+ .sort((a, b) => a.seq - b.seq)
89
+ ]
90
+ })
91
+ )
92
+ }
93
+
94
+
95
+ // 所有container位置(對應series)
96
+ export const seriesContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
97
+ computedData$: Observable<ComputedDataTypeMap<'series'>>
98
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
99
+ layout$: Observable<Layout>
100
+ }): Observable<SeriesContainerPosition[]> => {
101
+
102
+ const gridContainerPosition$ = combineLatest({
103
+ computedData: computedData$,
104
+ fullDataFormatter: fullDataFormatter$,
105
+ layout: layout$,
106
+ }).pipe(
107
+ switchMap(async (d) => d),
108
+ map(data => {
109
+
110
+ if (data.fullDataFormatter.separateSeries) {
111
+ // -- 依slotIndexes計算 --
112
+ return calcSeriesContainerLayout(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 } = calcSeriesContainerPosition(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 calcSeriesContainerLayout(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 } = calcSeriesContainerPosition(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
+ }
149
+ })
150
+ )
151
+
152
+ return gridContainerPosition$
153
+ }
154
+
155
+ export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$, seriesLabels$, seriesSeparate$ }: {
156
+ seriesContainerPosition$: Observable<SeriesContainerPosition[]>
157
+ seriesLabels$: Observable<string[]>
158
+ seriesSeparate$: Observable<boolean>
159
+ }) => {
160
+ return combineLatest({
161
+ seriesContainerPosition: seriesContainerPosition$,
162
+ seriesLabels: seriesLabels$,
163
+ seriesSeparate: seriesSeparate$,
164
+ }).pipe(
165
+ switchMap(async (d) => d),
166
+ map(data => {
167
+ return data.seriesSeparate
168
+ ? new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
169
+ return [seriesLabel, data.seriesContainerPosition[seriesIndex] ?? data.seriesContainerPosition[0]]
170
+ }))
171
+ : new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
172
+ return [seriesLabel, data.seriesContainerPosition[0]]
173
+ }))
174
+ })
175
+ )
176
+ }