@orbcharts/core 3.0.0-alpha.21

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 (166) hide show
  1. package/.gitignore +23 -0
  2. package/LICENSE +201 -0
  3. package/dist/orbcharts-core.es.js +5096 -0
  4. package/dist/orbcharts-core.umd.js +3 -0
  5. package/dist/src/AbstractChart.d.ts +17 -0
  6. package/dist/src/GridChart.d.ts +6 -0
  7. package/dist/src/MultiGridChart.d.ts +6 -0
  8. package/dist/src/MultiValueChart.d.ts +6 -0
  9. package/dist/src/RelationshipChart.d.ts +6 -0
  10. package/dist/src/SeriesChart.d.ts +6 -0
  11. package/dist/src/TreeChart.d.ts +6 -0
  12. package/dist/src/base/createBaseChart.d.ts +3 -0
  13. package/dist/src/base/createBasePlugin.d.ts +3 -0
  14. package/dist/src/defaults.d.ts +37 -0
  15. package/dist/src/defineGridPlugin.d.ts +1 -0
  16. package/dist/src/defineMultiGridPlugin.d.ts +1 -0
  17. package/dist/src/defineMultiValuePlugin.d.ts +1 -0
  18. package/dist/src/defineNoneDataPlugin.d.ts +1 -0
  19. package/dist/src/defineRelationshipPlugin.d.ts +1 -0
  20. package/dist/src/defineSeriesPlugin.d.ts +1 -0
  21. package/dist/src/defineTreePlugin.d.ts +1 -0
  22. package/dist/src/grid/computeGridData.d.ts +3 -0
  23. package/dist/src/grid/createGridContextObserver.d.ts +3 -0
  24. package/dist/src/grid/gridObservables.d.ts +25 -0
  25. package/dist/src/index.d.ts +15 -0
  26. package/dist/src/multiGrid/computeMultiGridData.d.ts +3 -0
  27. package/dist/src/multiGrid/createMultiGridContextObserver.d.ts +3 -0
  28. package/dist/src/multiGrid/multiGridObservables.d.ts +0 -0
  29. package/dist/src/multiValue/computeMultiValueData.d.ts +3 -0
  30. package/dist/src/multiValue/createMultiValueContextObserver.d.ts +3 -0
  31. package/dist/src/multiValue/multiValueObservables.d.ts +0 -0
  32. package/dist/src/relationship/computeRelationshipData.d.ts +3 -0
  33. package/dist/src/relationship/createRelationshipContextObserver.d.ts +3 -0
  34. package/dist/src/relationship/relationshipObservables.d.ts +0 -0
  35. package/dist/src/series/computeSeriesData.d.ts +3 -0
  36. package/dist/src/series/createSeriesContextObserver.d.ts +3 -0
  37. package/dist/src/series/seriesObservables.d.ts +8 -0
  38. package/dist/src/tree/computeTreeData.d.ts +3 -0
  39. package/dist/src/tree/createTreeContextObserver.d.ts +3 -0
  40. package/dist/src/tree/treeObservables.d.ts +0 -0
  41. package/dist/src/types/Axis.d.ts +1 -0
  42. package/dist/src/types/Chart.d.ts +41 -0
  43. package/dist/src/types/ChartParams.d.ts +36 -0
  44. package/dist/src/types/ComputedData.d.ts +28 -0
  45. package/dist/src/types/ComputedDataGrid.d.ts +10 -0
  46. package/dist/src/types/ComputedDataMultiGrid.d.ts +3 -0
  47. package/dist/src/types/ComputedDataMultiValue.d.ts +6 -0
  48. package/dist/src/types/ComputedDataRelationship.d.ts +18 -0
  49. package/dist/src/types/ComputedDataSeries.d.ts +6 -0
  50. package/dist/src/types/ComputedDataTree.d.ts +7 -0
  51. package/dist/src/types/ContextObserver.d.ts +28 -0
  52. package/dist/src/types/ContextObserverGrid.d.ts +18 -0
  53. package/dist/src/types/ContextObserverMultiGrid.d.ts +4 -0
  54. package/dist/src/types/ContextObserverMultiValue.d.ts +4 -0
  55. package/dist/src/types/ContextObserverRelationship.d.ts +4 -0
  56. package/dist/src/types/ContextObserverSeries.d.ts +8 -0
  57. package/dist/src/types/ContextObserverTree.d.ts +4 -0
  58. package/dist/src/types/ContextSubject.d.ts +15 -0
  59. package/dist/src/types/Data.d.ts +19 -0
  60. package/dist/src/types/DataFormatter.d.ts +40 -0
  61. package/dist/src/types/DataFormatterGrid.d.ts +20 -0
  62. package/dist/src/types/DataFormatterMultiGrid.d.ts +16 -0
  63. package/dist/src/types/DataFormatterMultiValue.d.ts +13 -0
  64. package/dist/src/types/DataFormatterRelationship.d.ts +5 -0
  65. package/dist/src/types/DataFormatterSeries.d.ts +10 -0
  66. package/dist/src/types/DataFormatterTree.d.ts +5 -0
  67. package/dist/src/types/DataGrid.d.ts +6 -0
  68. package/dist/src/types/DataMultiGrid.d.ts +6 -0
  69. package/dist/src/types/DataMultiValue.d.ts +6 -0
  70. package/dist/src/types/DataRelationship.d.ts +20 -0
  71. package/dist/src/types/DataSeries.d.ts +6 -0
  72. package/dist/src/types/DataTree.d.ts +13 -0
  73. package/dist/src/types/Event.d.ts +64 -0
  74. package/dist/src/types/Layout.d.ts +8 -0
  75. package/dist/src/types/Padding.d.ts +6 -0
  76. package/dist/src/types/Plugin.d.ts +37 -0
  77. package/dist/src/types/TransformData.d.ts +8 -0
  78. package/dist/src/types/index.d.ts +37 -0
  79. package/dist/src/utils/commonUtils.d.ts +8 -0
  80. package/dist/src/utils/d3Utils.d.ts +25 -0
  81. package/dist/src/utils/index.d.ts +4 -0
  82. package/dist/src/utils/observables.d.ts +14 -0
  83. package/dist/src/utils/orbchartsUtils.d.ts +20 -0
  84. package/dist/vite.config.d.ts +2 -0
  85. package/package.json +40 -0
  86. package/src/AbstractChart.ts +48 -0
  87. package/src/GridChart.ts +21 -0
  88. package/src/MultiGridChart.ts +21 -0
  89. package/src/MultiValueChart.ts +21 -0
  90. package/src/RelationshipChart.ts +21 -0
  91. package/src/SeriesChart.ts +21 -0
  92. package/src/TreeChart.ts +21 -0
  93. package/src/base/createBaseChart.ts +329 -0
  94. package/src/base/createBasePlugin.ts +89 -0
  95. package/src/defaults.ts +229 -0
  96. package/src/defineGridPlugin.ts +3 -0
  97. package/src/defineMultiGridPlugin.ts +3 -0
  98. package/src/defineMultiValuePlugin.ts +3 -0
  99. package/src/defineNoneDataPlugin.ts +4 -0
  100. package/src/defineRelationshipPlugin.ts +3 -0
  101. package/src/defineSeriesPlugin.ts +3 -0
  102. package/src/defineTreePlugin.ts +3 -0
  103. package/src/grid/computeGridData.ts +192 -0
  104. package/src/grid/createGridContextObserver.ts +91 -0
  105. package/src/grid/gridObservables.ts +359 -0
  106. package/src/index.ts +21 -0
  107. package/src/multiGrid/computeMultiGridData.ts +48 -0
  108. package/src/multiGrid/createMultiGridContextObserver.ts +12 -0
  109. package/src/multiGrid/multiGridObservables.ts +0 -0
  110. package/src/multiValue/computeMultiValueData.ts +127 -0
  111. package/src/multiValue/createMultiValueContextObserver.ts +12 -0
  112. package/src/multiValue/multiValueObservables.ts +0 -0
  113. package/src/relationship/computeRelationshipData.ts +101 -0
  114. package/src/relationship/createRelationshipContextObserver.ts +12 -0
  115. package/src/relationship/relationshipObservables.ts +0 -0
  116. package/src/series/computeSeriesData.ts +154 -0
  117. package/src/series/createSeriesContextObserver.ts +33 -0
  118. package/src/series/seriesObservables.ts +23 -0
  119. package/src/tree/computeTreeData.ts +104 -0
  120. package/src/tree/createTreeContextObserver.ts +12 -0
  121. package/src/tree/treeObservables.ts +0 -0
  122. package/src/types/Axis.ts +1 -0
  123. package/src/types/Chart.ts +46 -0
  124. package/src/types/ChartParams.ts +50 -0
  125. package/src/types/ComputedData.ts +66 -0
  126. package/src/types/ComputedDataGrid.ts +12 -0
  127. package/src/types/ComputedDataMultiGrid.ts +3 -0
  128. package/src/types/ComputedDataMultiValue.ts +10 -0
  129. package/src/types/ComputedDataRelationship.ts +20 -0
  130. package/src/types/ComputedDataSeries.ts +8 -0
  131. package/src/types/ComputedDataTree.ts +20 -0
  132. package/src/types/ContextObserver.ts +38 -0
  133. package/src/types/ContextObserverGrid.ts +16 -0
  134. package/src/types/ContextObserverMultiGrid.ts +5 -0
  135. package/src/types/ContextObserverMultiValue.ts +5 -0
  136. package/src/types/ContextObserverRelationship.ts +5 -0
  137. package/src/types/ContextObserverSeries.ts +8 -0
  138. package/src/types/ContextObserverTree.ts +5 -0
  139. package/src/types/ContextSubject.ts +18 -0
  140. package/src/types/Data.ts +45 -0
  141. package/src/types/DataFormatter.ts +99 -0
  142. package/src/types/DataFormatterGrid.ts +40 -0
  143. package/src/types/DataFormatterMultiGrid.ts +23 -0
  144. package/src/types/DataFormatterMultiValue.ts +19 -0
  145. package/src/types/DataFormatterRelationship.ts +23 -0
  146. package/src/types/DataFormatterSeries.ts +26 -0
  147. package/src/types/DataFormatterTree.ts +10 -0
  148. package/src/types/DataGrid.ts +11 -0
  149. package/src/types/DataMultiGrid.ts +7 -0
  150. package/src/types/DataMultiValue.ts +11 -0
  151. package/src/types/DataRelationship.ts +27 -0
  152. package/src/types/DataSeries.ts +11 -0
  153. package/src/types/DataTree.ts +18 -0
  154. package/src/types/Event.ts +114 -0
  155. package/src/types/Layout.ts +12 -0
  156. package/src/types/Padding.ts +6 -0
  157. package/src/types/Plugin.ts +60 -0
  158. package/src/types/TransformData.ts +8 -0
  159. package/src/types/index.ts +37 -0
  160. package/src/utils/commonUtils.ts +50 -0
  161. package/src/utils/d3Utils.ts +87 -0
  162. package/src/utils/index.ts +4 -0
  163. package/src/utils/observables.ts +198 -0
  164. package/src/utils/orbchartsUtils.ts +150 -0
  165. package/tsconfig.json +14 -0
  166. package/vite.config.js +45 -0
@@ -0,0 +1,359 @@
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
+ AxisPosition,
14
+ ChartType,
15
+ ChartParams,
16
+ ComputedDataTypeMap,
17
+ ComputedDatumTypeMap,
18
+ ContextObserverFn,
19
+ DataTypeMap,
20
+ DataFormatterTypeMap,
21
+ DataFormatterGrid,
22
+ DataFormatterContext,
23
+ DataFormatterValueAxis,
24
+ DataFormatterGroupAxis,
25
+ HighlightTarget,
26
+ Layout,
27
+ TransformData } from '../types'
28
+ import { getMinAndMaxGrid, transposeData } from '../utils/orbchartsUtils'
29
+ import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
30
+ import { highlightObservable } from '../utils/observables'
31
+
32
+ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
33
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
34
+ layout$: Observable<Layout>
35
+ }): Observable<TransformData> => {
36
+ const destroy$ = new Subject()
37
+
38
+ function calcAxesTransform ({ xAxis, yAxis, width, height }: {
39
+ xAxis: DataFormatterGroupAxis | DataFormatterValueAxis,
40
+ yAxis: DataFormatterValueAxis,
41
+ width: number,
42
+ height: number
43
+ }): TransformData {
44
+ if (!xAxis || !yAxis) {
45
+ return {
46
+ translate: [0, 0],
47
+ scale: [0, 0],
48
+ rotate: 0,
49
+ rotateX: 0,
50
+ rotateY: 0,
51
+ value: ''
52
+ }
53
+ }
54
+ // const width = size.width - fullChartParams.layout.left - fullChartParams.layout.right
55
+ // const height = size.height - fullChartParams.layout.top - fullChartParams.layout.bottom
56
+ let translateX = 0
57
+ let translateY = 0
58
+ let rotate = 0
59
+ let rotateX = 0
60
+ let rotateY = 0
61
+ if (xAxis.position === 'bottom') {
62
+ if (yAxis.position === 'left') {
63
+ rotateX = 180
64
+ translateY = height
65
+ } else if (yAxis.position === 'right') {
66
+ rotateX = 180
67
+ rotateY = 180
68
+ translateX = width
69
+ translateY = height
70
+ } else {
71
+ // 預設
72
+ rotateX = 180
73
+ translateY = height
74
+ }
75
+ } else if (xAxis.position === 'top') {
76
+ if (yAxis.position === 'left') {
77
+ } else if (yAxis.position === 'right') {
78
+ rotateY = 180
79
+ translateX = width
80
+ } else {
81
+ // 預設
82
+ rotateX = 180
83
+ translateY = height
84
+ }
85
+ } else if (xAxis.position === 'left') {
86
+ if (yAxis.position === 'bottom') {
87
+ rotate = -90
88
+ translateY = height
89
+ } else if (yAxis.position === 'top') {
90
+ rotate = -90
91
+ rotateY = 180
92
+ } else {
93
+ // 預設
94
+ rotateX = 180
95
+ translateY = height
96
+ }
97
+ } else if (xAxis.position === 'right') {
98
+ if (yAxis.position === 'bottom') {
99
+ rotate = -90
100
+ rotateX = 180
101
+ translateY = height
102
+ translateX = width
103
+ } else if (yAxis.position === 'top') {
104
+ rotate = -90
105
+ translateX = width
106
+ } else {
107
+ // 預設
108
+ rotateX = 180
109
+ translateY = height
110
+ }
111
+ }
112
+
113
+ // selection.style('transform', `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`)
114
+
115
+ return {
116
+ translate: [translateX, translateY],
117
+ scale: [0, 0],
118
+ rotate,
119
+ rotateX,
120
+ rotateY,
121
+ value: `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
122
+ }
123
+ }
124
+
125
+ return new Observable(subscriber => {
126
+ combineLatest({
127
+ fullDataFormatter: fullDataFormatter$,
128
+ layout: layout$
129
+ }).pipe(
130
+ takeUntil(destroy$)
131
+ ).subscribe(data => {
132
+ const axesTransformData = calcAxesTransform({
133
+ xAxis: data.fullDataFormatter.groupAxis,
134
+ yAxis: data.fullDataFormatter.valueAxis,
135
+ width: data.layout.width,
136
+ height: data.layout.height
137
+ })
138
+
139
+ subscriber.next(axesTransformData)
140
+ })
141
+
142
+ return function unscbscribe () {
143
+ destroy$.next(undefined)
144
+ }
145
+ })
146
+ }
147
+
148
+ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
149
+ computedData$: Observable<ComputedDataTypeMap<'grid'>>
150
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
151
+ layout$: Observable<Layout>
152
+ }): Observable<TransformData> => {
153
+ const destroy$ = new Subject()
154
+
155
+ function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, width, height }: {
156
+ data: ComputedDataTypeMap<'grid'>
157
+ groupAxis: DataFormatterGroupAxis
158
+ valueAxis: DataFormatterValueAxis
159
+ width: number
160
+ height: number
161
+ }): TransformData {
162
+ let translateX = 0
163
+ let translateY = 0
164
+ let scaleX = 0
165
+ let scaleY = 0
166
+
167
+ // -- groupScale --
168
+ const groupAxisWidth = (groupAxis.position === 'top' || groupAxis.position === 'bottom')
169
+ ? width
170
+ : height
171
+ const groupMin = 0
172
+ const groupMax = data[0] ? data[0].length - 1 : 0
173
+ const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'auto'
174
+ ? groupMin - groupAxis.scalePadding
175
+ : groupAxis.scaleDomain[0] as number - groupAxis.scalePadding
176
+ const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'auto'
177
+ ? groupMax + groupAxis.scalePadding
178
+ : groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
179
+
180
+ const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
181
+ maxValue: groupMax,
182
+ minValue: groupMin,
183
+ axisWidth: groupAxisWidth,
184
+ // scaleDomain: groupAxis.scaleDomain,
185
+ scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
186
+ scaleRange: [0, 1]
187
+ })
188
+
189
+ // -- translateX, scaleX --
190
+ const rangeMinX = groupScale(groupMin)
191
+ const rangeMaxX = groupScale(groupMax)
192
+ translateX = rangeMinX
193
+ const gWidth = rangeMaxX - rangeMinX
194
+ scaleX = gWidth / groupAxisWidth
195
+
196
+ // -- valueScale --
197
+ const filteredData = data.map((d, i) => {
198
+ return d.filter((_d, _i) => {
199
+ return _i >= groupScaleDomainMin && _i <= groupScaleDomainMax && _d.visible == true
200
+ })
201
+ })
202
+
203
+ const filteredMinAndMax = getMinAndMaxGrid(filteredData)
204
+
205
+ const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
206
+ ? height
207
+ : width
208
+
209
+ const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
210
+ maxValue: filteredMinAndMax[1],
211
+ minValue: filteredMinAndMax[0],
212
+ axisWidth: valueAxisWidth,
213
+ scaleDomain: valueAxis.scaleDomain,
214
+ scaleRange: valueAxis.scaleRange
215
+ })
216
+
217
+ // -- translateY, scaleY --
218
+ const minAndMax = getMinAndMaxGrid(data)
219
+ const rangeMinY = valueScale(minAndMax[0])
220
+ const rangeMaxY = valueScale(minAndMax[1])
221
+ translateY = rangeMinY
222
+ const gHeight = rangeMaxY - rangeMinY
223
+ scaleY = gHeight / valueAxisWidth
224
+
225
+ return {
226
+ translate: [translateX, translateY],
227
+ scale: [scaleX, scaleY],
228
+ rotate: 0,
229
+ rotateX: 0,
230
+ rotateY: 0,
231
+ value: `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`
232
+ }
233
+ }
234
+
235
+ return new Observable(subscriber => {
236
+ combineLatest({
237
+ computedData: computedData$,
238
+ fullDataFormatter: fullDataFormatter$,
239
+ layout: layout$
240
+ }).pipe(
241
+ takeUntil(destroy$)
242
+ ).subscribe(data => {
243
+ const dataAreaTransformData = calcGridDataAreaTransform ({
244
+ data: data.computedData,
245
+ groupAxis: data.fullDataFormatter.groupAxis,
246
+ valueAxis: data.fullDataFormatter.valueAxis,
247
+ width: data.layout.width,
248
+ height: data.layout.height
249
+ })
250
+
251
+ subscriber.next(dataAreaTransformData)
252
+ })
253
+
254
+ return function unscbscribe () {
255
+ destroy$.next(undefined)
256
+ }
257
+ })
258
+ }
259
+
260
+ export const gridAxesOppositeTransformObservable = ({ gridAxesTransform$ }: {
261
+ gridAxesTransform$: Observable<TransformData>
262
+ }): Observable<TransformData> => {
263
+ return gridAxesTransform$.pipe(
264
+ map(d => {
265
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
266
+ const translate: [number, number] = [0, 0] // 無需逆轉
267
+ const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
268
+ const rotate = d.rotate * -1
269
+ const rotateX = d.rotateX * -1
270
+ const rotateY = d.rotateY * -1
271
+ return {
272
+ translate,
273
+ scale,
274
+ rotate,
275
+ rotateX,
276
+ rotateY,
277
+ value: `translate(${translate[0]}px, ${translate[1]}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
278
+ }
279
+ }),
280
+ )
281
+ }
282
+
283
+ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
284
+ fullDataFormatter$: Observable<DataFormatterGrid>
285
+ layout$: Observable<Layout>
286
+ }): Observable<{
287
+ width: number;
288
+ height: number;
289
+ }> => {
290
+ const destroy$ = new Subject()
291
+
292
+ function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
293
+ xAxisPosition: AxisPosition
294
+ yAxisPosition: AxisPosition
295
+ width: number
296
+ height: number
297
+ }) {
298
+ if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
299
+ return { width, height }
300
+ } else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
301
+ return {
302
+ width: height,
303
+ height: width
304
+ }
305
+ }
306
+ }
307
+
308
+ return new Observable(subscriber => {
309
+ combineLatest({
310
+ fullDataFormatter: fullDataFormatter$,
311
+ layout: layout$
312
+ }).pipe(
313
+ takeUntil(destroy$),
314
+ // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
315
+ switchMap(async (d) => d),
316
+ ).subscribe(data => {
317
+
318
+ const axisSize = calcAxesSize({
319
+ xAxisPosition: data.fullDataFormatter.groupAxis.position,
320
+ yAxisPosition: data.fullDataFormatter.valueAxis.position,
321
+ width: data.layout.width,
322
+ height: data.layout.height,
323
+ })
324
+
325
+ subscriber.next(axisSize)
326
+
327
+ return function unsubscribe () {
328
+ destroy$.next(undefined)
329
+ }
330
+ })
331
+ })
332
+ }
333
+
334
+ // export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
335
+ // computedData$: Observable<ComputedDataTypeMap<'grid'>>
336
+ // fullChartParams$: Observable<ChartParams>
337
+ // event$: Subject<any>
338
+ // }): Observable<string[]> => {
339
+ // const datumList$ = computedData$.pipe(
340
+ // map(d => d.flat())
341
+ // )
342
+ // return highlightObservable ({ datumList$, fullChartParams$, event$ })
343
+ // }
344
+
345
+ export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
346
+ return computedData$.pipe(
347
+ map(data => {
348
+ const visibleComputedData = data
349
+ .map(d => {
350
+ return d.filter(_d => {
351
+ return _d.visible == true
352
+ })
353
+ })
354
+ .filter(d => d.length)
355
+ return visibleComputedData
356
+ })
357
+ )
358
+ }
359
+
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
1
+
2
+ export { SeriesChart } from './SeriesChart'
3
+ export { GridChart } from './GridChart'
4
+ export { MultiGridChart } from './MultiGridChart'
5
+ export { MultiValueChart } from './MultiValueChart'
6
+ export { RelationshipChart } from './RelationshipChart'
7
+ export { TreeChart } from './TreeChart'
8
+
9
+ export { defineSeriesPlugin } from './defineSeriesPlugin'
10
+ export { defineGridPlugin } from './defineGridPlugin'
11
+ export { defineMultiGridPlugin } from './defineMultiGridPlugin'
12
+ export { defineMultiValuePlugin } from './defineMultiValuePlugin'
13
+ export { defineNoneDataPlugin } from './defineNoneDataPlugin'
14
+ export { defineRelationshipPlugin } from './defineRelationshipPlugin'
15
+ export { defineTreePlugin } from './defineTreePlugin'
16
+
17
+ export * from './types'
18
+ export * from './utils'
19
+
20
+
21
+
@@ -0,0 +1,48 @@
1
+ import type { ComputedDataFn } from '../types/ComputedData'
2
+ import type { DataFormatterGrid } from '../types/DataFormatterGrid'
3
+ import type { ComputedDataGrid } from '../types/ComputedDataGrid'
4
+ import { computeGridData } from '../grid/computeGridData'
5
+
6
+ export const computeMultiGridData: ComputedDataFn<'multiGrid'> = ({ data = [], dataFormatter, chartParams, layout }) => {
7
+ if (!data.length) {
8
+ return []
9
+ }
10
+
11
+ let multiGridData: ComputedDataGrid[] = []
12
+
13
+ try {
14
+ multiGridData = data.map((d, i) => {
15
+ const dataFormatterGrid: DataFormatterGrid = {
16
+ ...dataFormatter.multiGrid[i],
17
+ type: `multiGrid_${i}` as any, // 非規範的名稱,用作 datum id 前綴
18
+ // colors: dataFormatter.colors,
19
+ colorsPredicate: dataFormatter.multiGrid[i].colorsPredicate,
20
+ visibleFilter: dataFormatter.visibleFilter as any, // 用any避開function參數型別不同
21
+ // padding: dataFormatter.padding,
22
+ tooltipContentFormat: dataFormatter.tooltipContentFormat as any, // 用any避開function參數型別不同
23
+ }
24
+ // const layoutGrid: ComputedLayoutBase = {
25
+ // width: layout.width,
26
+ // height: layout.height,
27
+ // top: layout.top,
28
+ // right: layout.right,
29
+ // bottom: layout.bottom,
30
+ // left: layout.left,
31
+ // rootWidth: layout.rootWidth,
32
+ // rootHeight: layout.rootHeight,
33
+ // // content: layout.content[i]
34
+ // }
35
+ return computeGridData({
36
+ data: d,
37
+ dataFormatter: dataFormatterGrid,
38
+ chartParams,
39
+ layout
40
+ })
41
+ })
42
+ } catch (e) {
43
+ // console.error(e)
44
+ throw Error(e)
45
+ }
46
+
47
+ return multiGridData
48
+ }
@@ -0,0 +1,12 @@
1
+ import type { ContextObserverFn } from '../types'
2
+
3
+ export const createMultiGridContextObserver: ContextObserverFn<'multiGrid'> = ({ subject, observer }) => {
4
+
5
+ return {
6
+ fullParams$: observer.fullParams$,
7
+ fullChartParams$: observer.fullChartParams$,
8
+ fullDataFormatter$: observer.fullDataFormatter$,
9
+ computedData$: observer.computedData$,
10
+ layout$: observer.layout$,
11
+ }
12
+ }
File without changes
@@ -0,0 +1,127 @@
1
+ import type { DataMultiValue, DataMultiValueDatum } from '../types/DataMultiValue'
2
+ import type { DataFormatterContext } from '../types/DataFormatter'
3
+ import type { ComputedDataFn } from '../types/ComputedData'
4
+ import type { ComputedDataMultiValue, ComputedDatumMultiValue } from '../types/ComputedDataMultiValue'
5
+ import { formatValueToLabel, createDefaultDatumId } from '../utils/orbchartsUtils'
6
+ import { createAxisLinearScale, createAxisPointScale } from '../utils/d3Utils'
7
+ import { getMinAndMaxValue } from '../utils/orbchartsUtils'
8
+
9
+ export const computeMultiValueData: ComputedDataFn<'multiValue'> = (context) => {
10
+ const { data, dataFormatter, chartParams, layout } = context
11
+ if (!data.length) {
12
+ return []
13
+ }
14
+
15
+ let computedDataMultiValue: ComputedDatumMultiValue[][] = []
16
+
17
+ try {
18
+ const dataMultiValue: DataMultiValueDatum[][] = data.map((d, i) => {
19
+ return d.map((_d, _i) => {
20
+ const datum: DataMultiValueDatum = typeof _d === 'number'
21
+ ? {
22
+ id: '',
23
+ label: '',
24
+ tooltipContent: '',
25
+ data: {},
26
+ value: _d
27
+ }
28
+ : {
29
+ id: _d.id ?? '',
30
+ label: _d.label ?? '',
31
+ tooltipContent: _d.tooltipContent ?? '',
32
+ data: _d.data ?? {},
33
+ value: _d.value
34
+ }
35
+
36
+ return datum
37
+ })
38
+ })
39
+
40
+ // x軸資料最小及最大值(第二維陣列中的第1筆為x軸資料)
41
+ const [xMinValue, xMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[0]))
42
+ // y軸資料最小及最大值(第二維陣列中的第2筆為y軸資料)
43
+ const [yMinValue, yMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[1]))
44
+
45
+ // const axisWidth = layout.width - dataFormatter.padding.left - dataFormatter.padding.right
46
+ // const axisHeight = layout.height - dataFormatter.padding.top - dataFormatter.padding.bottom
47
+ // const axisWidth = layout.width
48
+ // const axisHeight = layout.height
49
+ const xAxisWidth = (dataFormatter.xAxis.position === 'top' || dataFormatter.xAxis.position === 'bottom')
50
+ ? layout.width
51
+ : layout.height
52
+ const yAxisWidth = (dataFormatter.yAxis.position === 'left' || dataFormatter.yAxis.position === 'right')
53
+ ? layout.height
54
+ : layout.width
55
+
56
+ const xScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
57
+ maxValue: xMaxValue,
58
+ minValue: xMinValue,
59
+ axisWidth: xAxisWidth,
60
+ // scaleDomain: dataFormatter.xAxis.scaleDomain,
61
+ // scaleRange: dataFormatter.xAxis.scaleRange
62
+ scaleDomain: [xMinValue, xMaxValue],
63
+ scaleRange: [0, 1]
64
+ })
65
+ const yScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
66
+ maxValue: yMaxValue,
67
+ minValue: yMinValue,
68
+ axisWidth: yAxisWidth,
69
+ // scaleDomain: dataFormatter.yAxis.scaleDomain,
70
+ // scaleRange: dataFormatter.yAxis.scaleRange
71
+ scaleDomain: [yMinValue, yMaxValue],
72
+ scaleRange: [0, 1]
73
+ })
74
+
75
+ const _xScaleDoamin: [number, number] = [
76
+ dataFormatter.xAxis.scaleDomain[0] === 'auto' ? xMinValue : dataFormatter.xAxis.scaleDomain[0],
77
+ dataFormatter.xAxis.scaleDomain[1] === 'auto' ? xMaxValue : dataFormatter.xAxis.scaleDomain[1]
78
+ ]
79
+ const _yScaleDoamin: [number, number] = [
80
+ dataFormatter.yAxis.scaleDomain[0] === 'auto' ? yMinValue : dataFormatter.yAxis.scaleDomain[0],
81
+ dataFormatter.yAxis.scaleDomain[1] === 'auto' ? yMaxValue : dataFormatter.yAxis.scaleDomain[1]
82
+ ]
83
+ // 篩選顯示狀態
84
+ const visibleFilter = (datum: DataMultiValueDatum, rowIndex: number, columnIndex: number, context: DataFormatterContext<"multiValue">) => {
85
+ // 如果不在scale的範圍內則為false,不再做visibleFilter的判斷
86
+ if (columnIndex === 0 && datum.value != null && ((datum.value as number) < _xScaleDoamin[0] || datum.value > _xScaleDoamin[1])) {
87
+ return false
88
+ }
89
+ if (columnIndex === 1 && datum.value != null && (datum.value < _yScaleDoamin[0] || datum.value > _yScaleDoamin[1])) {
90
+ return false
91
+ }
92
+
93
+ return dataFormatter.visibleFilter(datum, rowIndex, columnIndex, context)
94
+ }
95
+
96
+ let index = 0
97
+
98
+ computedDataMultiValue = dataMultiValue.map((d, i) => {
99
+ return d.map((_d, _i) => {
100
+ const currentIndex = index
101
+ index++
102
+
103
+ const defaultId = createDefaultDatumId(dataFormatter.type, i, _i)
104
+ // const visible = dataFormatter.visibleFilter(_d, i, _i, context)
105
+ const visible = visibleFilter(_d, i, _i, context)
106
+
107
+ const computedDatum: ComputedDatumMultiValue = {
108
+ id: _d.id ? _d.id : defaultId,
109
+ index: currentIndex,
110
+ label: _d.label ? _d.label : defaultId,
111
+ tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
112
+ data: _d.data,
113
+ value: _d.value,
114
+ // valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
115
+ axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
116
+ visible
117
+ }
118
+ return computedDatum
119
+ })
120
+ })
121
+ } catch (e) {
122
+ // console.error(e)
123
+ throw Error(e)
124
+ }
125
+
126
+ return computedDataMultiValue
127
+ }
@@ -0,0 +1,12 @@
1
+ import type { ContextObserverFn } from '../types'
2
+
3
+ export const createMultiValueContextObserver: ContextObserverFn<'multiValue'> = ({ subject, observer }) => {
4
+
5
+ return {
6
+ fullParams$: observer.fullParams$,
7
+ fullChartParams$: observer.fullChartParams$,
8
+ fullDataFormatter$: observer.fullDataFormatter$,
9
+ computedData$: observer.computedData$,
10
+ layout$: observer.layout$,
11
+ }
12
+ }
File without changes
@@ -0,0 +1,101 @@
1
+ import type { DataRelationship, DataRelationshipObj, DataRelationshipList, Node, Edge } from '../types/DataRelationship'
2
+ import type { ComputedDataFn } from '../types/ComputedData'
3
+ import type { ComputedDataRelationship, ComputedNode, ComputedEdge } from '../types/ComputedDataRelationship'
4
+
5
+ export const computeRelationshipData: ComputedDataFn<'relationship'> = (context) => {
6
+ const { data, dataFormatter, chartParams } = context
7
+
8
+ let computedNodes: ComputedNode[] = []
9
+ let computedEdges: ComputedEdge[] = []
10
+
11
+ try {
12
+ // -- 取得nodes和edges資料 --
13
+ let nodes: Node[] = []
14
+ let edges: Edge[] = []
15
+ if ((data as DataRelationshipObj).nodes) {
16
+ nodes = (data as DataRelationshipObj).nodes
17
+ edges = (data as DataRelationshipObj).edges
18
+ } else if ((data as DataRelationshipList)[0]) {
19
+ nodes = (data as DataRelationshipList)[0]
20
+ edges = (data as DataRelationshipList)[1]
21
+ } else {
22
+ // 無值直接回傳
23
+ return {
24
+ nodes: [],
25
+ edges: []
26
+ } as ComputedDataRelationship
27
+ }
28
+
29
+ // -- nodes --
30
+ computedNodes = nodes.map((node, i) => {
31
+ return {
32
+ id: node.id,
33
+ index: i,
34
+ label: node.label ?? '',
35
+ tooltipContent: node.tooltipContent ? node.tooltipContent : dataFormatter.tooltipContentFormat(node, 0, i, context), // 0代表node
36
+ data: node.data ?? {},
37
+ value: node.value ?? 0,
38
+ startNodes: [], // 後面再取得資料
39
+ startNodeIds: [], // 後面再取得資料
40
+ endNodes: [], // 後面再取得資料
41
+ endNodeIds: [], // 後面再取得資料
42
+ visible: dataFormatter.visibleFilter(node, 0, i, context) // 0代表node
43
+ }
44
+ })
45
+
46
+ const NodesMap: Map<string, ComputedNode> = new Map(computedNodes.map(d => [d.id, d]))
47
+
48
+ // -- edges --
49
+ computedEdges = edges.map((edge, i) => {
50
+ return {
51
+ id: edge.id,
52
+ index: i,
53
+ label: edge.label ?? '',
54
+ tooltipContent: edge.tooltipContent ? edge.tooltipContent : dataFormatter.tooltipContentFormat(edge, 1, i, context), // 1代表edge
55
+ data: edge.data ?? {},
56
+ value: edge.value ?? 0,
57
+ startNode: NodesMap.get(edge.start),
58
+ startNodeId: edge.start,
59
+ endNode: NodesMap.get(edge.end),
60
+ endNodeId: edge.end,
61
+ visible: dataFormatter.visibleFilter(edge, 1, i, context) // 1代表edge
62
+ }
63
+ })
64
+
65
+ const StartNodesMap: Map<string, ComputedNode[]> = (function () {
66
+ const _StartNodesMap = new Map()
67
+ computedEdges.forEach(edge => {
68
+ const startNodes: ComputedNode[] = _StartNodesMap.get(edge.endNodeId) ?? []
69
+ startNodes.push(edge.startNode)
70
+ _StartNodesMap.set(edge.endNodeId, startNodes)
71
+ })
72
+ return _StartNodesMap
73
+ })()
74
+
75
+ const EndNodesMap: Map<string, ComputedNode[]> = (function () {
76
+ const _EndNodesMap = new Map()
77
+ computedEdges.forEach(edge => {
78
+ const endNodes: ComputedNode[] = _EndNodesMap.get(edge.startNodeId) ?? []
79
+ endNodes.push(edge.endNode)
80
+ _EndNodesMap.set(edge.startNodeId, endNodes)
81
+ })
82
+ return _EndNodesMap
83
+ })()
84
+
85
+ // -- 補齊nodes資料 --
86
+ Array.from(NodesMap).forEach(([nodeId, node]) => {
87
+ node.startNodes = StartNodesMap.get(nodeId)
88
+ node.startNodeIds = node.startNodes.map(d => d.id)
89
+ node.endNodes = EndNodesMap.get(nodeId)
90
+ node.endNodeIds = node.endNodes.map(d => d.id)
91
+ })
92
+ } catch (e) {
93
+ // console.error(e)
94
+ throw Error(e)
95
+ }
96
+
97
+ return {
98
+ nodes: computedNodes,
99
+ edges: computedEdges
100
+ }
101
+ }