@orbcharts/core 3.0.0-beta.1 → 3.0.0-beta.10

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 (45) hide show
  1. package/dist/orbcharts-core.es.js +3239 -2854
  2. package/dist/orbcharts-core.umd.js +4 -4
  3. package/dist/src/defaults.d.ts +24 -23
  4. package/dist/src/utils/d3Scale.d.ts +28 -0
  5. package/dist/src/utils/gridObservables.d.ts +29 -19
  6. package/dist/src/utils/index.d.ts +1 -1
  7. package/dist/src/utils/multiGridObservables.d.ts +2 -2
  8. package/dist/src/utils/multiValueObservables.d.ts +73 -0
  9. package/dist/src/utils/orbchartsUtils.d.ts +24 -10
  10. package/dist/src/utils/relationshipObservables.d.ts +13 -0
  11. package/dist/src/utils/seriesObservables.d.ts +4 -4
  12. package/dist/src/utils/treeObservables.d.ts +2 -5
  13. package/package.json +2 -2
  14. package/src/GridChart.ts +2 -2
  15. package/src/MultiGridChart.ts +2 -2
  16. package/src/MultiValueChart.ts +2 -2
  17. package/src/RelationshipChart.ts +2 -2
  18. package/src/SeriesChart.ts +2 -2
  19. package/src/TreeChart.ts +2 -2
  20. package/src/base/createBaseChart.ts +13 -13
  21. package/src/base/validators/chartParamsValidator.ts +6 -6
  22. package/src/defaults.ts +63 -47
  23. package/src/grid/computedDataFn.ts +4 -4
  24. package/src/grid/contextObserverCallback.ts +58 -37
  25. package/src/grid/dataFormatterValidator.ts +14 -14
  26. package/src/multiGrid/computedDataFn.ts +2 -2
  27. package/src/multiValue/computedDataFn.ts +81 -147
  28. package/src/multiValue/contextObserverCallback.ts +150 -2
  29. package/src/relationship/computedDataFn.ts +94 -60
  30. package/src/relationship/contextObserverCallback.ts +68 -0
  31. package/src/tree/computedDataFn.ts +9 -10
  32. package/src/tree/contextObserverCallback.ts +6 -9
  33. package/src/utils/d3Scale.ts +198 -0
  34. package/src/utils/gridObservables.ts +320 -248
  35. package/src/utils/index.ts +1 -1
  36. package/src/utils/multiGridObservables.ts +75 -49
  37. package/src/utils/multiValueObservables.ts +662 -0
  38. package/src/utils/observables.ts +30 -12
  39. package/src/utils/orbchartsUtils.ts +90 -65
  40. package/src/utils/relationshipObservables.ts +85 -0
  41. package/src/utils/seriesObservables.ts +7 -7
  42. package/src/utils/treeObservables.ts +44 -33
  43. package/src/utils/validator.ts +5 -4
  44. package/dist/src/utils/d3Utils.d.ts +0 -19
  45. package/src/utils/d3Utils.ts +0 -108
@@ -45,6 +45,15 @@ export function resizeObservable(elem: HTMLElement | Element): Observable<DOMRec
45
45
  })
46
46
  }
47
47
 
48
+ interface HighlightTargetValue {
49
+ id: string | null
50
+ label: string | null
51
+ seriesLabel: string | null
52
+ groupLabel: string | null
53
+ categoryLabel: string | null
54
+ highlightDefault: string | null
55
+ }
56
+
48
57
  // 通用 highlight Observable
49
58
  export const highlightObservable = <T extends ChartType, D>({ datumList$, fullChartParams$, event$ }: {
50
59
  datumList$: Observable<D[]>
@@ -54,11 +63,12 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
54
63
  const destroy$ = new Subject()
55
64
 
56
65
  // 預設的highlight
57
- const highlightDefault$ = fullChartParams$.pipe(
66
+ const highlightDefault$: Observable<HighlightTargetValue> = fullChartParams$.pipe(
58
67
  takeUntil(destroy$),
59
68
  map(d => {
60
69
  return {
61
70
  id: null,
71
+ label: null,
62
72
  seriesLabel: null,
63
73
  groupLabel: null,
64
74
  categoryLabel: null,
@@ -69,22 +79,25 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
69
79
  )
70
80
 
71
81
  // 事件觸發的highlight
72
- const highlightMouseover$ = event$.pipe(
82
+ const highlightMouseover$: Observable<HighlightTargetValue> = event$.pipe(
73
83
  takeUntil(destroy$),
74
84
  // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
75
85
  filter(d => d.eventName === 'mouseover'),
76
86
  // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
77
- map(d => {
78
- return (d as any).datum
87
+ map(_d => {
88
+ const d = _d as any
89
+ return d.datum
79
90
  ? {
80
- id: ((d as any).datum as any).id,
81
- seriesLabel: ((d as any).datum as any).seriesLabel,
82
- groupLabel: ((d as any).datum as any).groupLabel,
83
- categoryLabel: ((d as any).datum as any).categoryLabel,
91
+ id: d.datum.id,
92
+ label: d.datum.label,
93
+ seriesLabel: d.datum.seriesLabel,
94
+ groupLabel: d.datum.groupLabel,
95
+ categoryLabel: d.datum.categoryLabel,
84
96
  highlightDefault: null
85
97
  }
86
98
  : {
87
99
  id: null,
100
+ label: null,
88
101
  seriesLabel: null,
89
102
  groupLabel: null,
90
103
  categoryLabel: null,
@@ -102,9 +115,14 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
102
115
  switchMap(d => highlightDefault$)
103
116
  )
104
117
 
105
- function getDatumIds (datumList: ComputedDatumTypeMap<T>[], id: string | null) {
106
- const datum = datumList.find(d => (d as ComputedDatumBase).id === id)
107
- return datum ? [datum] : []
118
+ // function getDatumIds (datumList: ComputedDatumTypeMap<T>[], id: string | null) {
119
+ // const datum = datumList.find(d => (d as ComputedDatumBase).id === id)
120
+ // return datum ? [datum] : []
121
+ // }
122
+ function getDatumIds (datumList: ComputedDatumTypeMap<T>[], id: string | null, label: string | null) {
123
+ return id == null && label == null
124
+ ? []
125
+ : datumList.filter(d => (d as ComputedDatumBase).id === id || (d as ComputedDatumBase).label === label)
108
126
  }
109
127
 
110
128
  function getSeriesIds (datumList: ComputedDatumTypeMap<T>[], seriesLabel: string | null) {
@@ -136,7 +154,7 @@ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullCh
136
154
  ).subscribe(data => {
137
155
  let datumList: ComputedDatumTypeMap<T>[] = []
138
156
  if (data.fullChartParams.highlightTarget === 'datum') {
139
- datumList = getDatumIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.id)
157
+ datumList = getDatumIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.id, data.target.label)
140
158
  } else if (data.fullChartParams.highlightTarget === 'series') {
141
159
  datumList = getSeriesIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.seriesLabel)
142
160
  } else if (data.fullChartParams.highlightTarget === 'group') {
@@ -13,11 +13,12 @@ import type {
13
13
  DataMultiValue,
14
14
  DataMultiValueDatum,
15
15
  DataMultiValueValue,
16
+ ComputedLayoutDatumMultiValue,
16
17
  DataFormatterContainer,
17
18
  SeriesDirection,
18
19
  DataFormatterGridGrid,
19
- SeriesContainerPosition,
20
- GridContainerPosition,
20
+ ContainerPosition,
21
+ ContainerPositionScaled,
21
22
  Layout
22
23
  } from '../../lib/core-types'
23
24
  import { isPlainObject } from './commonUtils'
@@ -29,8 +30,11 @@ export function formatValueToLabel (value: any, valueFormatter: string | ((text:
29
30
  return d3.format(valueFormatter as string)!(value)
30
31
  }
31
32
 
32
- export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex: number, levelThreeIndex?: number) {
33
- let text = `${chartTypeOrPrefix}_${levelOneIndex}_${levelTwoIndex}`
33
+ export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex?: number, levelThreeIndex?: number) {
34
+ let text = `${chartTypeOrPrefix}_${levelOneIndex}`
35
+ if (levelTwoIndex != null) {
36
+ text += `_${levelTwoIndex}`
37
+ }
34
38
  if (levelThreeIndex != null) {
35
39
  text += `_${levelThreeIndex}`
36
40
  }
@@ -45,6 +49,11 @@ export function createDefaultGroupLabel (chartTypeOrPrefix: string, groupIndex:
45
49
  return `${chartTypeOrPrefix}_group${groupIndex}`
46
50
  }
47
51
 
52
+ export function createDefaultCategoryLabel () {
53
+ // return `${chartTypeOrPrefix}_category`
54
+ return '' // 空值
55
+ }
56
+
48
57
  export function createGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
49
58
  transposedDataGrid: DataGridDatum[][],
50
59
  dataFormatterGrid: DataFormatterGridGrid
@@ -114,76 +123,125 @@ export function createMultiGridGroupLabels ({ transposedDataGrid, dataFormatterG
114
123
  }
115
124
 
116
125
  // 取得最小及最大值 - 數字陣列
117
- export function getMinAndMax (data: number[]): [number, number] {
118
- const defaultMinAndMax: [number, number] = [0, 0] // default
126
+ export function getMinMax (data: number[]): [number, number] {
127
+ const defaultMinMax: [number, number] = [0, 0] // default
119
128
  if (!data.length) {
120
- return defaultMinAndMax
129
+ return defaultMinMax
121
130
  }
122
- const minAndMax: [number, number] = data.reduce((prev, current) => {
131
+ const minMax: [number, number] = data.reduce((prev, current) => {
123
132
  // [min, max]
124
133
  return [
125
134
  current < prev[0] ? current : prev[0],
126
135
  current > prev[1] ? current : prev[1]
127
136
  ]
128
137
  }, [data[0], data[0]])
129
- return minAndMax
138
+ return minMax
130
139
  }
131
140
 
132
141
  // 取得最小及最大值 - datum格式陣列資料
133
- export function getMinAndMaxValue (data: DatumValue[]): [number, number] {
142
+ export function getMinMaxValue (data: DatumValue[]): [number, number] {
134
143
  const arr = data
135
144
  .filter(d => d != null && d.value != null)
136
145
  .map(d => d.value )
137
- return getMinAndMax(arr)
146
+ return getMinMax(arr)
138
147
  }
139
148
 
140
149
  // 取得最小及最大值 - Series Data
141
- export function getMinAndMaxSeries (data: DataSeries): [number, number] {
150
+ export function getMinMaxSeries (data: DataSeries): [number, number] {
142
151
  const flatData: (DataSeriesValue | DataSeriesDatum)[] = data[0] && Array.isArray((data as (DataSeriesValue | DataSeriesDatum)[][])[0])
143
152
  ? data.flat()
144
153
  : data as (DataSeriesValue | DataSeriesDatum)[]
145
154
  const arr = flatData
146
155
  .filter(d => (d == null || (isPlainObject(d) && (d as DataSeriesDatum).value == null)) === false) // 過濾掉null &
147
156
  .map(d => typeof d === 'number' ? d : d.value )
148
- return getMinAndMax(arr)
157
+ return getMinMax(arr)
149
158
  }
150
159
 
151
160
  // 取得最小及最大值 - Grid Data
152
- export function getMinAndMaxGrid (data: DataGrid): [number, number] {
161
+ export function getMinMaxGrid (data: DataGrid): [number, number] {
153
162
  const flatData: (DataGridValue | DataGridDatum)[] = data.flat()
154
163
  const arr = flatData
155
164
  .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
156
165
  .map(d => typeof d === 'number' ? d : d.value )
157
- return getMinAndMax(arr)
166
+ return getMinMax(arr)
158
167
  }
159
168
 
160
169
  // 取得最小及最大值 - MultiGrid Data
161
- export function getMinAndMaxMultiGrid (data: DataMultiGrid): [number, number] {
170
+ export function getMinMaxMultiGrid (data: DataMultiGrid): [number, number] {
162
171
  const flatData: (DataGridValue | DataGridDatum)[] = data.flat().flat()
163
172
  const arr = flatData
164
173
  .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
165
174
  .map(d => typeof d === 'number' ? d : d.value )
166
- return getMinAndMax(arr)
175
+ return getMinMax(arr)
167
176
  }
168
177
 
169
178
  // 取得最小及最大值 - MultiValue Data
170
- export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number = 2): [number, number] {
171
- const flatData: (DataMultiValueDatum | DataMultiValueValue)[] = data.flat().filter((d, i) => i == valueIndex)
172
- const arr = flatData
173
- .filter(d => (d == null || (isPlainObject(d) && (d as DataMultiValueDatum).value == null)) === false) // 過濾掉null
174
- .map(d => typeof d === 'number' ? d : d.value )
175
- return getMinAndMax(arr)
179
+ export function getMinMaxMultiValue (data: DataMultiValue, valueIndex: number): [number, number] {
180
+ const arr: number[] = data
181
+ .map(d => {
182
+ if (Array.isArray(d)) {
183
+ return d[valueIndex] ?? null
184
+ } else if (isPlainObject(d)) {
185
+ return (d as DataMultiValueDatum).value[valueIndex] ?? null
186
+ } else {
187
+ return null
188
+ }
189
+ })
190
+ .filter(d => d != null)
191
+ return getMinMax(arr)
192
+ }
193
+
194
+ export function getMinMaxMultiValueXY ({ data, minX, maxX, minY, maxY }: {
195
+ data: ComputedLayoutDatumMultiValue[][]
196
+ minX: number
197
+ maxX: number
198
+ minY: number
199
+ maxY: number
200
+ }) {
201
+ let filteredData: ComputedLayoutDatumMultiValue[][] = []
202
+ let minXDatum: ComputedLayoutDatumMultiValue | null = null
203
+ let maxXDatum: ComputedLayoutDatumMultiValue | null = null
204
+ let minYDatum: ComputedLayoutDatumMultiValue | null = null
205
+ let maxYDatum: ComputedLayoutDatumMultiValue | null = null
206
+
207
+ for (let categoryData of data) {
208
+ for (let datum of categoryData) {
209
+ if (datum.axisX >= minX && datum.axisX <= maxX && datum.axisY >= minY && datum.axisY <= maxY) {
210
+ filteredData.push(categoryData)
211
+ if (minXDatum == null || datum.axisX < minXDatum.axisX) {
212
+ minXDatum = datum
213
+ }
214
+ if (maxXDatum == null || datum.axisX > maxXDatum.axisX) {
215
+ maxXDatum = datum
216
+ }
217
+ if (minYDatum == null || datum.axisY < minYDatum.axisY) {
218
+ minYDatum = datum
219
+ }
220
+ if (maxYDatum == null || datum.axisY > maxYDatum.axisY) {
221
+ maxYDatum = datum
222
+ }
223
+ }
224
+ }
225
+ }
226
+
227
+ return {
228
+ minXDatum,
229
+ maxXDatum,
230
+ minYDatum,
231
+ maxYDatum,
232
+ filteredData
233
+ }
176
234
  }
177
235
 
178
236
  // @Q@ 待處理
179
237
  // // 取得最小及最大值 - Relationship Data
180
- // export function getMinAndMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
238
+ // export function getMinMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
181
239
 
182
240
  // }
183
241
 
184
242
  // @Q@ 待處理
185
243
  // // 取得最小及最大值 - Tree Data
186
- // export function getMinAndMaxTree (data: DataTree): [number, number] {
244
+ // export function getMinMaxTree (data: DataTree): [number, number] {
187
245
 
188
246
  // }
189
247
 
@@ -213,31 +271,13 @@ export function transposeData<T> (seriesDirection: SeriesDirection, data: T[][])
213
271
 
214
272
 
215
273
  export function seriesColorPredicate (seriesIndex: number, chartParams: ChartParams) {
216
- return seriesIndex < chartParams.colors[chartParams.colorScheme].series.length
217
- ? chartParams.colors[chartParams.colorScheme].series[seriesIndex]
218
- : chartParams.colors[chartParams.colorScheme].series[
219
- seriesIndex % chartParams.colors[chartParams.colorScheme].series.length
274
+ return seriesIndex < chartParams.colors[chartParams.colorScheme].label.length
275
+ ? chartParams.colors[chartParams.colorScheme].label[seriesIndex]
276
+ : chartParams.colors[chartParams.colorScheme].label[
277
+ seriesIndex % chartParams.colors[chartParams.colorScheme].label.length
220
278
  ]
221
279
  }
222
280
 
223
- // export function calcSeriesContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
224
- // const { gap, rowAmount, columnAmount } = container
225
- // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
226
- // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
227
- // const x = columnIndex * width + (columnIndex * gap)
228
- // const y = rowIndex * height + (rowIndex * gap)
229
- // // const translate: [number, number] = [x, y]
230
-
231
- // return {
232
- // // translate,
233
- // startX: x,
234
- // startY: y,
235
- // centerX: x + width / 2,
236
- // centerY: y + height / 2,
237
- // width,
238
- // height
239
- // }
240
- // }
241
281
 
242
282
  // 計算預設欄列數量
243
283
  // 規則1.rowAmount*columnAmount要大於或等於amount,並且數字要盡可能小
@@ -251,7 +291,7 @@ function calcGridDimensions (amount: number): { rowAmount: number; columnAmount:
251
291
  return { rowAmount, columnAmount }
252
292
  }
253
293
 
254
- export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): SeriesContainerPosition[] {
294
+ export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): ContainerPosition[] {
255
295
  const { gap } = container
256
296
  const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
257
297
  // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
@@ -284,22 +324,7 @@ export function calcSeriesContainerLayout (layout: Layout, container: DataFormat
284
324
  })
285
325
  }
286
326
 
287
- // export function calcGridContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
288
- // const { gap, rowAmount, columnAmount } = container
289
- // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
290
- // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
291
- // const x = columnIndex * width + (columnIndex * gap)
292
- // const y = rowIndex * height + (rowIndex * gap)
293
- // const translate: [number, number] = [x, y]
294
- // const scale: [number, number] = [width / layout.width, height / layout.height]
295
-
296
- // return {
297
- // translate,
298
- // scale
299
- // }
300
- // }
301
-
302
- export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): GridContainerPosition[] {
327
+ export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): ContainerPositionScaled[] {
303
328
  const { gap } = container
304
329
  const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
305
330
  // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
@@ -318,7 +343,7 @@ export function calcGridContainerLayout (layout: Layout, container: DataFormatte
318
343
  const translate: [number, number] = [x, y]
319
344
  const scale: [number, number] = [width / layout.width, height / layout.height]
320
345
 
321
- return {
346
+ return {
322
347
  slotIndex: index,
323
348
  rowIndex,
324
349
  columnIndex,
@@ -0,0 +1,85 @@
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
+ ComputedDataRelationship,
15
+ ComputedDataTypeMap,
16
+ ComputedNode,
17
+ ComputedEdge,
18
+ DataFormatterTree } from '../../lib/core-types'
19
+
20
+
21
+ export const categoryLabelsObservable = (
22
+ CategoryNodeMap$: Observable<Map<string, ComputedNode[]>>,
23
+ CategoryEdgeMap$: Observable<Map<string, ComputedEdge[]>>
24
+ ): Observable<string[]> => {
25
+ return combineLatest({
26
+ CategoryNodeMap: CategoryNodeMap$,
27
+ CategoryEdgeMap: CategoryEdgeMap$
28
+ }).pipe(
29
+ switchMap(async d => d),
30
+ map(data => {
31
+ return [...Array.from(data.CategoryNodeMap.keys()), ...Array.from(data.CategoryEdgeMap.keys())]
32
+ }),
33
+ distinctUntilChanged((a, b) => {
34
+ return JSON.stringify(a).length === JSON.stringify(b).length
35
+ }),
36
+ )
37
+ }
38
+
39
+ export const NodeMapObservable = (computedData$: Observable<ComputedDataRelationship>) => {
40
+ return computedData$.pipe(
41
+ map(data => {
42
+ const nodeMap = new Map<string, ComputedNode>()
43
+ data.nodes.forEach(node => {
44
+ nodeMap.set(node.id, node)
45
+ })
46
+ return nodeMap
47
+ }),
48
+ )
49
+ }
50
+
51
+ export const EdgeMapObservable = (computedData$: Observable<ComputedDataRelationship>) => {
52
+ return computedData$.pipe(
53
+ map(data => {
54
+ const edgeMap = new Map<string, ComputedEdge>()
55
+ data.edges.forEach(edge => {
56
+ edgeMap.set(edge.id, edge)
57
+ })
58
+ return edgeMap
59
+ }),
60
+ )
61
+ }
62
+
63
+ // 所有可見的節點
64
+ export const relationshipVisibleComputedDataObservable = ({ computedData$, NodeMap$ }: {
65
+ computedData$: Observable<ComputedDataRelationship>
66
+ NodeMap$: Observable<Map<string, ComputedNode>>
67
+ }) => {
68
+ return combineLatest({
69
+ computedData: computedData$,
70
+ NodeMap: NodeMap$
71
+ }).pipe(
72
+ switchMap(async d => d),
73
+ map(data => {
74
+ return {
75
+ nodes: data.computedData.nodes.filter(node => node.visible),
76
+ edges: data.computedData.edges
77
+ .filter(edge => edge.visible)
78
+ // 依照節點是否存在篩選
79
+ .filter(edge => {
80
+ return data.NodeMap.has(edge.startNode.id) && data.NodeMap.has(edge.endNode.id)
81
+ })
82
+ }
83
+ })
84
+ )
85
+ }
@@ -14,7 +14,7 @@ import type {
14
14
  ComputedDatumSeries,
15
15
  ComputedDataTypeMap,
16
16
  DataFormatterTypeMap,
17
- SeriesContainerPosition,
17
+ ContainerPosition,
18
18
  Layout } from '../../lib/core-types'
19
19
  import { calcSeriesContainerLayout } from './orbchartsUtils'
20
20
 
@@ -97,7 +97,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
97
97
  computedData$: Observable<ComputedDataTypeMap<'series'>>
98
98
  fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
99
99
  layout$: Observable<Layout>
100
- }): Observable<SeriesContainerPosition[]> => {
100
+ }): Observable<ContainerPosition[]> => {
101
101
 
102
102
  const gridContainerPosition$ = combineLatest({
103
103
  computedData: computedData$,
@@ -113,7 +113,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
113
113
  // return data.computedData.map((seriesData, seriesIndex) => {
114
114
  // const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
115
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)
116
+ // const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
117
117
  // return {
118
118
  // slotIndex: seriesIndex,
119
119
  // rowIndex,
@@ -132,7 +132,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
132
132
  // const columnIndex = 0
133
133
  // const rowIndex = 0
134
134
  // return data.computedData.map((seriesData, seriesIndex) => {
135
- // const { startX, startY, centerX, centerY, width, height } = calcSeriesContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
135
+ // const { startX, startY, centerX, centerY, width, height } = calcContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
136
136
  // return {
137
137
  // slotIndex: 0,
138
138
  // rowIndex,
@@ -153,7 +153,7 @@ export const seriesContainerPositionObservable = ({ computedData$, fullDataForma
153
153
  }
154
154
 
155
155
  export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$, seriesLabels$, separateSeries$ }: {
156
- seriesContainerPosition$: Observable<SeriesContainerPosition[]>
156
+ seriesContainerPosition$: Observable<ContainerPosition[]>
157
157
  seriesLabels$: Observable<string[]>
158
158
  separateSeries$: Observable<boolean>
159
159
  }) => {
@@ -165,10 +165,10 @@ export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$,
165
165
  switchMap(async (d) => d),
166
166
  map(data => {
167
167
  return data.separateSeries
168
- ? new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
168
+ ? new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
169
169
  return [seriesLabel, data.seriesContainerPosition[seriesIndex] ?? data.seriesContainerPosition[0]]
170
170
  }))
171
- : new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
171
+ : new Map<string, ContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
172
172
  return [seriesLabel, data.seriesContainerPosition[0]]
173
173
  }))
174
174
  })
@@ -34,42 +34,53 @@ export const nodeListObservable = ({ computedData$ }: { computedData$: Observabl
34
34
  )
35
35
  }
36
36
 
37
- export const existCategoryLabelsObservable = ({ nodeList$, fullDataFormatter$ }: {
38
- nodeList$: Observable<ComputedDataTree[]>
39
- fullDataFormatter$: Observable<DataFormatterTree>
40
- }) => {
37
+ // export const categoryLabelsObservable = ({ nodeList$, fullDataFormatter$ }: {
38
+ // nodeList$: Observable<ComputedDataTree[]>
39
+ // fullDataFormatter$: Observable<DataFormatterTree>
40
+ // }) => {
41
41
 
42
- const categoryLabels$ = fullDataFormatter$.pipe(
43
- map(d => d.categoryLabels),
44
- distinctUntilChanged((a, b) => {
45
- return JSON.stringify(a).length === JSON.stringify(b).length
46
- }),
47
- )
42
+ // const categoryLabels$ = fullDataFormatter$.pipe(
43
+ // map(d => d.categoryLabels),
44
+ // distinctUntilChanged((a, b) => {
45
+ // return JSON.stringify(a).length === JSON.stringify(b).length
46
+ // }),
47
+ // )
48
48
 
49
- return combineLatest({
50
- nodeList: nodeList$,
51
- categoryLabels: categoryLabels$
52
- }).pipe(
53
- switchMap(async d => d),
54
- map(data => {
55
- const CurrentLabelSet = new Set(data.categoryLabels)
56
- const ExistLabelSet = new Set(
57
- data.nodeList.filter(node => node.visible).map(node => node.categoryLabel)
58
- )
59
- // 加入已存在的label(data.nodeList有,但是dataFormatter.categoryLabels沒有)
60
- Array.from(ExistLabelSet).forEach(label => {
61
- if (!CurrentLabelSet.has(label)) {
62
- CurrentLabelSet.add(label)
63
- }
64
- })
65
- // 移除不存在的label(dataFormatter.categoryLabels有,但是data.nodeList沒有)
66
- Array.from(CurrentLabelSet).forEach(label => {
67
- if (!ExistLabelSet.has(label)) {
68
- ExistLabelSet.delete(label)
69
- }
70
- })
49
+ // return combineLatest({
50
+ // nodeList: nodeList$,
51
+ // categoryLabels: categoryLabels$
52
+ // }).pipe(
53
+ // switchMap(async d => d),
54
+ // map(data => {
55
+ // const CurrentLabelSet = new Set(data.categoryLabels)
56
+ // const ExistLabelSet = new Set(
57
+ // data.nodeList.filter(node => node.visible).map(node => node.categoryLabel)
58
+ // )
59
+ // // 加入已存在的label(data.nodeList有,但是dataFormatter.categoryLabels沒有)
60
+ // Array.from(ExistLabelSet).forEach(label => {
61
+ // if (!CurrentLabelSet.has(label)) {
62
+ // CurrentLabelSet.add(label)
63
+ // }
64
+ // })
65
+ // // 移除不存在的label(dataFormatter.categoryLabels有,但是data.nodeList沒有)
66
+ // Array.from(CurrentLabelSet).forEach(label => {
67
+ // if (!ExistLabelSet.has(label)) {
68
+ // ExistLabelSet.delete(label)
69
+ // }
70
+ // })
71
71
 
72
- return Array.from(CurrentLabelSet)
72
+ // return Array.from(CurrentLabelSet)
73
+ // }),
74
+ // distinctUntilChanged((a, b) => {
75
+ // return JSON.stringify(a).length === JSON.stringify(b).length
76
+ // }),
77
+ // )
78
+ // }
79
+
80
+ export const categoryLabelsObservable = (CategoryDataMap$: Observable<Map<string, ComputedDataTree[]>>) => {
81
+ return CategoryDataMap$.pipe(
82
+ map(data => {
83
+ return Array.from(data.keys())
73
84
  }),
74
85
  distinctUntilChanged((a, b) => {
75
86
  return JSON.stringify(a).length === JSON.stringify(b).length
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ ColorType,
2
3
  ValidatorResult,
3
4
  ToBeTypes,
4
5
  ToBeOption,
@@ -40,14 +41,14 @@ function getInvalidColumn<T> (data: T, rules: Partial<ValidatorRule<T>>) {
40
41
  }
41
42
  // "toBeOption" 的測試
42
43
  const testOption: {[key in ToBeOption]: (value: any) => boolean} = {
43
- ColorType: (value: any) => {
44
+ ColorType: (value: ColorType) => {
44
45
  return value === 'none'
45
- || value === 'series'
46
+ || value === 'label'
46
47
  || value === 'primary'
47
48
  || value === 'secondary'
48
- || value === 'white'
49
+ || value === 'labelContrast'
49
50
  || value === 'background'
50
- }
51
+ },
51
52
  }
52
53
 
53
54
  const failColumn = Object.keys(data).find((columnName: string) => {
@@ -1,19 +0,0 @@
1
- import * as d3 from 'd3';
2
- export declare const createAxisLinearScale: ({ maxValue, minValue, axisWidth, scaleDomain, scaleRange, }: {
3
- maxValue: number;
4
- minValue: number;
5
- axisWidth: number;
6
- scaleDomain: [number | "min" | "auto", number | "max" | "auto"];
7
- scaleRange: [number, number];
8
- }) => d3.ScaleLinear<number, number, never>;
9
- export declare const createAxisPointScale: ({ axisLabels, axisWidth, padding }: {
10
- axisLabels: string[];
11
- axisWidth: number;
12
- padding?: number;
13
- }) => d3.ScalePoint<string>;
14
- export declare const createAxisQuantizeScale: ({ axisLabels, axisWidth, padding, reverse }: {
15
- axisLabels: string[] | Date[];
16
- axisWidth: number;
17
- padding?: number;
18
- reverse?: boolean;
19
- }) => d3.ScaleQuantize<number, never>;