@orbcharts/core 3.0.5 → 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.
Files changed (68) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +2217 -2164
  3. package/dist/orbcharts-core.umd.js +5 -5
  4. package/lib/core-types.ts +7 -7
  5. package/package.json +46 -46
  6. package/src/AbstractChart.ts +57 -57
  7. package/src/GridChart.ts +24 -24
  8. package/src/MultiGridChart.ts +24 -24
  9. package/src/MultiValueChart.ts +24 -24
  10. package/src/RelationshipChart.ts +24 -24
  11. package/src/SeriesChart.ts +24 -24
  12. package/src/TreeChart.ts +24 -24
  13. package/src/base/createBaseChart.ts +524 -524
  14. package/src/base/createBasePlugin.ts +154 -154
  15. package/src/base/validators/chartOptionsValidator.ts +23 -23
  16. package/src/base/validators/chartParamsValidator.ts +133 -133
  17. package/src/base/validators/elementValidator.ts +13 -13
  18. package/src/base/validators/pluginsValidator.ts +14 -14
  19. package/src/defaults.ts +284 -284
  20. package/src/defineGridPlugin.ts +3 -3
  21. package/src/defineMultiGridPlugin.ts +3 -3
  22. package/src/defineMultiValuePlugin.ts +3 -3
  23. package/src/defineNoneDataPlugin.ts +4 -4
  24. package/src/defineRelationshipPlugin.ts +3 -3
  25. package/src/defineSeriesPlugin.ts +3 -3
  26. package/src/defineTreePlugin.ts +3 -3
  27. package/src/grid/computedDataFn.ts +129 -129
  28. package/src/grid/contextObserverCallback.ts +209 -201
  29. package/src/grid/dataFormatterValidator.ts +125 -125
  30. package/src/grid/dataValidator.ts +12 -12
  31. package/src/grid/gridObservables.ts +698 -694
  32. package/src/index.ts +20 -20
  33. package/src/multiGrid/computedDataFn.ts +123 -123
  34. package/src/multiGrid/contextObserverCallback.ts +109 -75
  35. package/src/multiGrid/dataFormatterValidator.ts +120 -120
  36. package/src/multiGrid/dataValidator.ts +12 -12
  37. package/src/multiGrid/multiGridObservables.ts +366 -357
  38. package/src/multiValue/computedDataFn.ts +113 -113
  39. package/src/multiValue/contextObserverCallback.ts +328 -328
  40. package/src/multiValue/dataFormatterValidator.ts +94 -94
  41. package/src/multiValue/dataValidator.ts +12 -12
  42. package/src/multiValue/multiValueObservables.ts +865 -865
  43. package/src/relationship/computedDataFn.ts +159 -159
  44. package/src/relationship/contextObserverCallback.ts +80 -80
  45. package/src/relationship/dataFormatterValidator.ts +13 -13
  46. package/src/relationship/dataValidator.ts +13 -13
  47. package/src/relationship/relationshipObservables.ts +84 -84
  48. package/src/series/computedDataFn.ts +88 -88
  49. package/src/series/contextObserverCallback.ts +132 -132
  50. package/src/series/dataFormatterValidator.ts +46 -46
  51. package/src/series/dataValidator.ts +12 -12
  52. package/src/series/seriesObservables.ts +209 -209
  53. package/src/tree/computedDataFn.ts +129 -129
  54. package/src/tree/contextObserverCallback.ts +58 -58
  55. package/src/tree/dataFormatterValidator.ts +13 -13
  56. package/src/tree/dataValidator.ts +13 -13
  57. package/src/tree/treeObservables.ts +105 -105
  58. package/src/utils/commonUtils.ts +55 -55
  59. package/src/utils/d3Scale.ts +198 -198
  60. package/src/utils/errorMessage.ts +40 -40
  61. package/src/utils/index.ts +3 -3
  62. package/src/utils/observables.ts +308 -308
  63. package/src/utils/orbchartsUtils.ts +396 -396
  64. package/src/utils/validator.ts +126 -126
  65. package/tsconfig.base.json +13 -13
  66. package/tsconfig.json +2 -2
  67. package/vite-env.d.ts +6 -6
  68. package/vite.config.js +22 -22
@@ -1,47 +1,47 @@
1
- import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
2
- import { validateColumns } from '../utils/validator'
3
-
4
- export const dataFormatterValidator: DataFormatterValidator<'series'> = (dataFormatter: DataFormatterTypeMap<'series'>) => {
5
- const result = validateColumns(dataFormatter, {
6
- visibleFilter: {
7
- toBeTypes: ['Function']
8
- },
9
- sort: {
10
- toBeTypes: ['Function', 'null']
11
- },
12
- seriesLabels: {
13
- toBeTypes: ['string[]']
14
- },
15
- container: {
16
- toBeTypes: ['object']
17
- },
18
- separateSeries: {
19
- toBeTypes: ['boolean']
20
- },
21
- sumSeries: {
22
- toBeTypes: ['boolean']
23
- }
24
- })
25
- if (dataFormatter.container) {
26
- const containerResult = validateColumns(dataFormatter.container, {
27
- columnAmount: {
28
- toBeTypes: ['number']
29
- },
30
- rowAmount: {
31
- toBeTypes: ['number']
32
- },
33
- columnGap: {
34
- toBe: '"auto" | number',
35
- test: (value: any) => value === 'auto' || typeof value === 'number'
36
- },
37
- rowGap: {
38
- toBe: '"auto" | number',
39
- test: (value: any) => value === 'auto' || typeof value === 'number'
40
- },
41
- })
42
- if (containerResult.status === 'error') {
43
- return containerResult
44
- }
45
- }
46
- return result
1
+ import type { DataFormatterValidator, DataFormatterTypeMap } from '../../lib/core-types'
2
+ import { validateColumns } from '../utils/validator'
3
+
4
+ export const dataFormatterValidator: DataFormatterValidator<'series'> = (dataFormatter: DataFormatterTypeMap<'series'>) => {
5
+ const result = validateColumns(dataFormatter, {
6
+ visibleFilter: {
7
+ toBeTypes: ['Function']
8
+ },
9
+ sort: {
10
+ toBeTypes: ['Function', 'null']
11
+ },
12
+ seriesLabels: {
13
+ toBeTypes: ['string[]']
14
+ },
15
+ container: {
16
+ toBeTypes: ['object']
17
+ },
18
+ separateSeries: {
19
+ toBeTypes: ['boolean']
20
+ },
21
+ sumSeries: {
22
+ toBeTypes: ['boolean']
23
+ }
24
+ })
25
+ if (dataFormatter.container) {
26
+ const containerResult = validateColumns(dataFormatter.container, {
27
+ columnAmount: {
28
+ toBeTypes: ['number']
29
+ },
30
+ rowAmount: {
31
+ toBeTypes: ['number']
32
+ },
33
+ columnGap: {
34
+ toBe: '"auto" | number',
35
+ test: (value: any) => value === 'auto' || typeof value === 'number'
36
+ },
37
+ rowGap: {
38
+ toBe: '"auto" | number',
39
+ test: (value: any) => value === 'auto' || typeof value === 'number'
40
+ },
41
+ })
42
+ if (containerResult.status === 'error') {
43
+ return containerResult
44
+ }
45
+ }
46
+ return result
47
47
  }
@@ -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<'series'> = (data: DataTypeMap<'series'>) => {
5
- const result = validateColumns({ data }, {
6
- data: {
7
- toBe: '(DataSeriesDatum | DataSeriesValue)[][] | (DataSeriesDatum | DataSeriesValue)[]',
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<'series'> = (data: DataTypeMap<'series'>) => {
5
+ const result = validateColumns({ data }, {
6
+ data: {
7
+ toBe: '(DataSeriesDatum | DataSeriesValue)[][] | (DataSeriesDatum | DataSeriesValue)[]',
8
+ // 畢免資料量過大檢查不完,不深度檢查
9
+ test: (value) => Array.isArray(value)
10
+ }
11
+ })
12
+ return result
13
13
  }
@@ -1,210 +1,210 @@
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
- ContainerPosition,
18
- Layout } from '../../lib/core-types'
19
- import { calcContainerPosition } from '../utils/orbchartsUtils'
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
-
35
- export const separateSeriesObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
36
- return fullDataFormatter$.pipe(
37
- map(data => data.separateSeries),
38
- distinctUntilChanged(),
39
- )
40
- }
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
-
56
- export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
57
- return computedData$.pipe(
58
- map(data => {
59
- return data
60
- .filter(series => series.length)
61
- .map(series => {
62
- return series[0].seriesLabel
63
- })
64
- }),
65
- distinctUntilChanged((a, b) => {
66
- return JSON.stringify(a) === JSON.stringify(b)
67
- }),
68
- )
69
- }
70
-
71
- export const seriesVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
72
- return computedData$.pipe(
73
- map(data => {
74
- return data.map(series => {
75
- return series.filter(datum => datum.visible != false)
76
- })
77
- })
78
- )
79
- }
80
-
81
- export const seriesComputedSortedDataObservable = ({ computedData$, separateSeries$, separateLabel$, sumSeries$, datumLabels$ }: {
82
- computedData$: Observable<ComputedDataTypeMap<'series'>>,
83
- separateSeries$: Observable<boolean>,
84
- separateLabel$: Observable<boolean>,
85
- sumSeries$: Observable<boolean>,
86
- datumLabels$: Observable<string[]>
87
- }) => {
88
- return combineLatest({
89
- computedData: computedData$,
90
- separateSeries: separateSeries$,
91
- separateLabel: separateLabel$,
92
- sumSeries: sumSeries$,
93
- datumLabels: datumLabels$,
94
- }).pipe(
95
- switchMap(async (d) => d),
96
- map(data => {
97
-
98
- // sum series
99
- const sumData: ComputedDatumSeries[][] = data.sumSeries == true
100
- ? data.computedData.map(d => {
101
- return [
102
- // 加總為一筆資料
103
- d.reduce((acc, current) => {
104
- if (acc == null) {
105
- // * 取得第一筆資料
106
- return current
107
- }
108
- // 加總 value
109
- acc.value = acc.value + current.value
110
- return acc
111
- }, null)
112
- ]
113
- })
114
- : data.computedData
115
-
116
- // separate series
117
- const separateSeriesData: ComputedDatumSeries[][] = data.separateSeries == true
118
- // 有拆分的話每個series為一組
119
- ? sumData
120
- // 無拆分的話所有資料為一組
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
- })
144
- .flat()
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
- })
158
- })
159
- )
160
- }
161
-
162
-
163
- // 所有container位置(對應series)
164
- export const seriesContainerPositionObservable = ({ computedSortedData$, fullDataFormatter$, layout$ }: {
165
- computedSortedData$: Observable<ComputedDatumSeries[][]>
166
- fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
167
- layout$: Observable<Layout>
168
- }): Observable<ContainerPosition[]> => {
169
-
170
- const gridContainerPosition$ = combineLatest({
171
- computedSortedData: computedSortedData$,
172
- fullDataFormatter: fullDataFormatter$,
173
- layout: layout$,
174
- }).pipe(
175
- switchMap(async (d) => d),
176
- map(data => {
177
-
178
- // 已分類資料的分類數量
179
- const amount = data.computedSortedData.length
180
-
181
- return calcContainerPosition(data.layout, data.fullDataFormatter.container, amount)
182
- })
183
- )
184
-
185
- return gridContainerPosition$
186
- }
187
-
188
- export const datumContainerPositionMapObservable = ({ seriesContainerPosition$, computedSortedData$ }: {
189
- seriesContainerPosition$: Observable<ContainerPosition[]>
190
- computedSortedData$: Observable<ComputedDatumSeries[][]>
191
- }) => {
192
- return combineLatest({
193
- seriesContainerPosition: seriesContainerPosition$,
194
- computedSortedData: computedSortedData$,
195
- }).pipe(
196
- switchMap(async (d) => d),
197
- map(data => {
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
- )
208
- })
209
- )
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
+ ContainerPosition,
18
+ Layout } from '../../lib/core-types'
19
+ import { calcContainerPosition } from '../utils/orbchartsUtils'
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
+
35
+ export const separateSeriesObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
36
+ return fullDataFormatter$.pipe(
37
+ map(data => data.separateSeries),
38
+ distinctUntilChanged(),
39
+ )
40
+ }
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
+
56
+ export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
57
+ return computedData$.pipe(
58
+ map(data => {
59
+ return data
60
+ .filter(series => series.length)
61
+ .map(series => {
62
+ return series[0].seriesLabel
63
+ })
64
+ }),
65
+ distinctUntilChanged((a, b) => {
66
+ return JSON.stringify(a) === JSON.stringify(b)
67
+ }),
68
+ )
69
+ }
70
+
71
+ export const seriesVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
72
+ return computedData$.pipe(
73
+ map(data => {
74
+ return data.map(series => {
75
+ return series.filter(datum => datum.visible != false)
76
+ })
77
+ })
78
+ )
79
+ }
80
+
81
+ export const seriesComputedSortedDataObservable = ({ computedData$, separateSeries$, separateLabel$, sumSeries$, datumLabels$ }: {
82
+ computedData$: Observable<ComputedDataTypeMap<'series'>>,
83
+ separateSeries$: Observable<boolean>,
84
+ separateLabel$: Observable<boolean>,
85
+ sumSeries$: Observable<boolean>,
86
+ datumLabels$: Observable<string[]>
87
+ }) => {
88
+ return combineLatest({
89
+ computedData: computedData$,
90
+ separateSeries: separateSeries$,
91
+ separateLabel: separateLabel$,
92
+ sumSeries: sumSeries$,
93
+ datumLabels: datumLabels$,
94
+ }).pipe(
95
+ switchMap(async (d) => d),
96
+ map(data => {
97
+
98
+ // sum series
99
+ const sumData: ComputedDatumSeries[][] = data.sumSeries == true
100
+ ? data.computedData.map(d => {
101
+ return [
102
+ // 加總為一筆資料
103
+ d.reduce((acc, current) => {
104
+ if (acc == null) {
105
+ // * 取得第一筆資料
106
+ return current
107
+ }
108
+ // 加總 value
109
+ acc.value = acc.value + current.value
110
+ return acc
111
+ }, null)
112
+ ]
113
+ })
114
+ : data.computedData
115
+
116
+ // separate series
117
+ const separateSeriesData: ComputedDatumSeries[][] = data.separateSeries == true
118
+ // 有拆分的話每個series為一組
119
+ ? sumData
120
+ // 無拆分的話所有資料為一組
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
+ })
144
+ .flat()
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
+ })
158
+ })
159
+ )
160
+ }
161
+
162
+
163
+ // 所有container位置(對應series)
164
+ export const seriesContainerPositionObservable = ({ computedSortedData$, fullDataFormatter$, layout$ }: {
165
+ computedSortedData$: Observable<ComputedDatumSeries[][]>
166
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
167
+ layout$: Observable<Layout>
168
+ }): Observable<ContainerPosition[]> => {
169
+
170
+ const gridContainerPosition$ = combineLatest({
171
+ computedSortedData: computedSortedData$,
172
+ fullDataFormatter: fullDataFormatter$,
173
+ layout: layout$,
174
+ }).pipe(
175
+ switchMap(async (d) => d),
176
+ map(data => {
177
+
178
+ // 已分類資料的分類數量
179
+ const amount = data.computedSortedData.length
180
+
181
+ return calcContainerPosition(data.layout, data.fullDataFormatter.container, amount)
182
+ })
183
+ )
184
+
185
+ return gridContainerPosition$
186
+ }
187
+
188
+ export const datumContainerPositionMapObservable = ({ seriesContainerPosition$, computedSortedData$ }: {
189
+ seriesContainerPosition$: Observable<ContainerPosition[]>
190
+ computedSortedData$: Observable<ComputedDatumSeries[][]>
191
+ }) => {
192
+ return combineLatest({
193
+ seriesContainerPosition: seriesContainerPosition$,
194
+ computedSortedData: computedSortedData$,
195
+ }).pipe(
196
+ switchMap(async (d) => d),
197
+ map(data => {
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
+ )
208
+ })
209
+ )
210
210
  }