@orbcharts/core 3.0.0-alpha.61 → 3.0.0-alpha.63

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 (215) hide show
  1. package/LICENSE +200 -200
  2. package/dist/lib/core-types.d.ts +1 -0
  3. package/dist/orbcharts-core.es.js +3418 -2726
  4. package/dist/orbcharts-core.umd.js +6 -2
  5. package/dist/src/AbstractChart.d.ts +5 -3
  6. package/dist/src/GridChart.d.ts +1 -1
  7. package/dist/src/MultiGridChart.d.ts +1 -1
  8. package/dist/src/MultiValueChart.d.ts +1 -1
  9. package/dist/src/RelationshipChart.d.ts +1 -1
  10. package/dist/src/SeriesChart.d.ts +1 -1
  11. package/dist/src/TreeChart.d.ts +1 -1
  12. package/dist/src/base/createBaseChart.d.ts +1 -1
  13. package/dist/src/base/createBasePlugin.d.ts +1 -1
  14. package/dist/src/base/validators/chartOptionsValidator.d.ts +3 -0
  15. package/dist/src/base/validators/chartParamsValidator.d.ts +3 -0
  16. package/dist/src/base/validators/elementValidator.d.ts +3 -0
  17. package/dist/src/base/validators/pluginsValidator.d.ts +3 -0
  18. package/dist/src/defaults.d.ts +1 -16
  19. package/dist/src/defineGridPlugin.d.ts +1 -1
  20. package/dist/src/defineMultiGridPlugin.d.ts +1 -1
  21. package/dist/src/defineMultiValuePlugin.d.ts +1 -1
  22. package/dist/src/defineNoneDataPlugin.d.ts +1 -1
  23. package/dist/src/defineRelationshipPlugin.d.ts +1 -1
  24. package/dist/src/defineSeriesPlugin.d.ts +1 -1
  25. package/dist/src/defineTreePlugin.d.ts +1 -1
  26. package/dist/src/grid/computedDataFn.d.ts +4 -0
  27. package/dist/src/grid/contextObserverCallback.d.ts +3 -0
  28. package/dist/src/grid/dataFormatterValidator.d.ts +3 -0
  29. package/dist/src/grid/dataValidator.d.ts +3 -0
  30. package/dist/src/index.d.ts +1 -1
  31. package/dist/src/multiGrid/computedDataFn.d.ts +3 -0
  32. package/dist/src/multiGrid/contextObserverCallback.d.ts +3 -0
  33. package/dist/src/multiGrid/dataFormatterValidator.d.ts +3 -0
  34. package/dist/src/multiGrid/dataValidator.d.ts +3 -0
  35. package/dist/src/multiValue/computedDataFn.d.ts +3 -0
  36. package/dist/src/multiValue/contextObserverCallback.d.ts +3 -0
  37. package/dist/src/multiValue/dataFormatterValidator.d.ts +3 -0
  38. package/dist/src/multiValue/dataValidator.d.ts +3 -0
  39. package/dist/src/relationship/computedDataFn.d.ts +3 -0
  40. package/dist/src/relationship/contextObserverCallback.d.ts +3 -0
  41. package/dist/src/relationship/dataFormatterValidator.d.ts +3 -0
  42. package/dist/src/relationship/dataValidator.d.ts +3 -0
  43. package/dist/src/series/computedDataFn.d.ts +3 -0
  44. package/dist/src/series/contextObserverCallback.d.ts +3 -0
  45. package/dist/src/series/dataFormatterValidator.d.ts +3 -0
  46. package/dist/src/series/dataValidator.d.ts +3 -0
  47. package/dist/src/tree/computedDataFn.d.ts +3 -0
  48. package/dist/src/tree/contextObserverCallback.d.ts +3 -0
  49. package/dist/src/tree/dataFormatterValidator.d.ts +3 -0
  50. package/dist/src/tree/dataValidator.d.ts +3 -0
  51. package/dist/src/utils/commonUtils.d.ts +1 -0
  52. package/dist/src/utils/errorMessage.d.ts +14 -0
  53. package/dist/src/{grid → utils}/gridObservables.d.ts +2 -2
  54. package/dist/src/utils/index.d.ts +7 -3
  55. package/dist/src/{multiGrid → utils}/multiGridObservables.d.ts +1 -1
  56. package/dist/src/utils/observables.d.ts +2 -1
  57. package/dist/src/utils/orbchartsUtils.d.ts +1 -12
  58. package/dist/src/{series → utils}/seriesObservables.d.ts +3 -3
  59. package/dist/src/{tree → utils}/treeObservables.d.ts +1 -1
  60. package/dist/src/utils/validator.d.ts +3 -0
  61. package/lib/core-types.ts +7 -0
  62. package/package.json +42 -41
  63. package/src/AbstractChart.ts +57 -48
  64. package/src/GridChart.ts +24 -20
  65. package/src/MultiGridChart.ts +24 -20
  66. package/src/MultiValueChart.ts +24 -20
  67. package/src/RelationshipChart.ts +24 -20
  68. package/src/SeriesChart.ts +24 -20
  69. package/src/TreeChart.ts +24 -20
  70. package/src/base/createBaseChart.ts +500 -388
  71. package/src/base/createBasePlugin.ts +152 -95
  72. package/src/base/validators/chartOptionsValidator.ts +24 -0
  73. package/src/base/validators/chartParamsValidator.ts +134 -0
  74. package/src/base/validators/elementValidator.ts +14 -0
  75. package/src/base/validators/pluginsValidator.ts +15 -0
  76. package/src/defaults.ts +232 -228
  77. package/src/defineGridPlugin.ts +3 -3
  78. package/src/defineMultiGridPlugin.ts +3 -3
  79. package/src/defineMultiValuePlugin.ts +3 -3
  80. package/src/defineNoneDataPlugin.ts +4 -4
  81. package/src/defineRelationshipPlugin.ts +3 -3
  82. package/src/defineSeriesPlugin.ts +3 -3
  83. package/src/defineTreePlugin.ts +3 -3
  84. package/src/grid/{computeGridData.ts → computedDataFn.ts} +129 -134
  85. package/src/grid/{createGridContextObserver.ts → contextObserverCallback.ts} +155 -155
  86. package/src/grid/dataFormatterValidator.ts +102 -0
  87. package/src/grid/dataValidator.ts +13 -0
  88. package/src/index.ts +20 -21
  89. package/src/multiGrid/{computeMultiGridData.ts → computedDataFn.ts} +123 -130
  90. package/src/multiGrid/{createMultiGridContextObserver.ts → contextObserverCallback.ts} +41 -41
  91. package/src/multiGrid/dataFormatterValidator.ts +116 -0
  92. package/src/multiGrid/dataValidator.ts +13 -0
  93. package/src/multiValue/{computeMultiValueData.ts → computedDataFn.ts} +176 -179
  94. package/src/multiValue/{createMultiValueContextObserver.ts → contextObserverCallback.ts} +12 -12
  95. package/src/multiValue/dataFormatterValidator.ts +10 -0
  96. package/src/multiValue/dataValidator.ts +10 -0
  97. package/src/relationship/{computeRelationshipData.ts → computedDataFn.ts} +125 -118
  98. package/src/relationship/{createRelationshipContextObserver.ts → contextObserverCallback.ts} +12 -12
  99. package/src/relationship/dataFormatterValidator.ts +10 -0
  100. package/src/relationship/dataValidator.ts +10 -0
  101. package/src/series/{computeSeriesData.ts → computedDataFn.ts} +88 -90
  102. package/src/series/{createSeriesContextObserver.ts → contextObserverCallback.ts} +100 -93
  103. package/src/series/dataFormatterValidator.ts +42 -0
  104. package/src/series/dataValidator.ts +13 -0
  105. package/src/tree/{computeTreeData.ts → computedDataFn.ts} +130 -132
  106. package/src/tree/{createTreeContextObserver.ts → contextObserverCallback.ts} +61 -61
  107. package/src/tree/dataFormatterValidator.ts +14 -0
  108. package/src/tree/dataValidator.ts +14 -0
  109. package/src/utils/commonUtils.ts +54 -50
  110. package/src/utils/d3Utils.ts +108 -108
  111. package/src/utils/errorMessage.ts +43 -0
  112. package/src/{grid → utils}/gridObservables.ts +611 -614
  113. package/src/utils/index.ts +10 -4
  114. package/src/{multiGrid → utils}/multiGridObservables.ts +366 -365
  115. package/src/utils/observables.ts +219 -202
  116. package/src/utils/orbchartsUtils.ts +352 -349
  117. package/src/{series → utils}/seriesObservables.ts +175 -175
  118. package/src/{tree → utils}/treeObservables.ts +94 -94
  119. package/src/utils/validator.ts +126 -0
  120. package/tsconfig.base.json +13 -13
  121. package/tsconfig.json +2 -2
  122. package/vite-env.d.ts +7 -0
  123. package/vite.config.js +22 -22
  124. package/dist/src/grid/computeGridData.d.ts +0 -6
  125. package/dist/src/grid/createGridContextObserver.d.ts +0 -3
  126. package/dist/src/multiGrid/computeMultiGridData.d.ts +0 -3
  127. package/dist/src/multiGrid/createMultiGridContextObserver.d.ts +0 -3
  128. package/dist/src/multiValue/computeMultiValueData.d.ts +0 -3
  129. package/dist/src/multiValue/createMultiValueContextObserver.d.ts +0 -3
  130. package/dist/src/relationship/computeRelationshipData.d.ts +0 -3
  131. package/dist/src/relationship/createRelationshipContextObserver.d.ts +0 -3
  132. package/dist/src/series/computeSeriesData.d.ts +0 -3
  133. package/dist/src/series/createSeriesContextObserver.d.ts +0 -3
  134. package/dist/src/tree/computeTreeData.d.ts +0 -3
  135. package/dist/src/tree/createTreeContextObserver.d.ts +0 -3
  136. package/dist/src/types/Axis.d.ts +0 -1
  137. package/dist/src/types/Chart.d.ts +0 -45
  138. package/dist/src/types/ChartParams.d.ts +0 -36
  139. package/dist/src/types/ComputedData.d.ts +0 -42
  140. package/dist/src/types/ComputedDataGrid.d.ts +0 -5
  141. package/dist/src/types/ComputedDataMultiGrid.d.ts +0 -3
  142. package/dist/src/types/ComputedDataMultiValue.d.ts +0 -6
  143. package/dist/src/types/ComputedDataRelationship.d.ts +0 -18
  144. package/dist/src/types/ComputedDataSeries.d.ts +0 -5
  145. package/dist/src/types/ComputedDataTree.d.ts +0 -7
  146. package/dist/src/types/ContextObserver.d.ts +0 -28
  147. package/dist/src/types/ContextObserverGrid.d.ts +0 -41
  148. package/dist/src/types/ContextObserverMultiGrid.d.ts +0 -15
  149. package/dist/src/types/ContextObserverMultiValue.d.ts +0 -4
  150. package/dist/src/types/ContextObserverRelationship.d.ts +0 -4
  151. package/dist/src/types/ContextObserverSeries.d.ts +0 -27
  152. package/dist/src/types/ContextObserverTree.d.ts +0 -11
  153. package/dist/src/types/ContextSubject.d.ts +0 -15
  154. package/dist/src/types/Data.d.ts +0 -19
  155. package/dist/src/types/DataFormatter.d.ts +0 -41
  156. package/dist/src/types/DataFormatterGrid.d.ts +0 -34
  157. package/dist/src/types/DataFormatterMultiGrid.d.ts +0 -20
  158. package/dist/src/types/DataFormatterMultiValue.d.ts +0 -18
  159. package/dist/src/types/DataFormatterRelationship.d.ts +0 -10
  160. package/dist/src/types/DataFormatterSeries.d.ts +0 -19
  161. package/dist/src/types/DataFormatterTree.d.ts +0 -7
  162. package/dist/src/types/DataGrid.d.ts +0 -6
  163. package/dist/src/types/DataMultiGrid.d.ts +0 -6
  164. package/dist/src/types/DataMultiValue.d.ts +0 -7
  165. package/dist/src/types/DataRelationship.d.ts +0 -21
  166. package/dist/src/types/DataSeries.d.ts +0 -6
  167. package/dist/src/types/DataTree.d.ts +0 -15
  168. package/dist/src/types/Event.d.ts +0 -56
  169. package/dist/src/types/Layout.d.ts +0 -8
  170. package/dist/src/types/Padding.d.ts +0 -6
  171. package/dist/src/types/Plugin.d.ts +0 -37
  172. package/dist/src/types/TransformData.d.ts +0 -8
  173. package/dist/src/types/index.d.ts +0 -37
  174. package/src/types/Axis.ts +0 -1
  175. package/src/types/Chart.ts +0 -54
  176. package/src/types/ChartParams.ts +0 -51
  177. package/src/types/ComputedData.ts +0 -84
  178. package/src/types/ComputedDataGrid.ts +0 -14
  179. package/src/types/ComputedDataMultiGrid.ts +0 -3
  180. package/src/types/ComputedDataMultiValue.ts +0 -9
  181. package/src/types/ComputedDataRelationship.ts +0 -20
  182. package/src/types/ComputedDataSeries.ts +0 -8
  183. package/src/types/ComputedDataTree.ts +0 -20
  184. package/src/types/ContextObserver.ts +0 -38
  185. package/src/types/ContextObserverGrid.ts +0 -43
  186. package/src/types/ContextObserverMultiGrid.ts +0 -17
  187. package/src/types/ContextObserverMultiValue.ts +0 -5
  188. package/src/types/ContextObserverRelationship.ts +0 -5
  189. package/src/types/ContextObserverSeries.ts +0 -29
  190. package/src/types/ContextObserverTree.ts +0 -11
  191. package/src/types/ContextSubject.ts +0 -18
  192. package/src/types/Data.ts +0 -45
  193. package/src/types/DataFormatter.ts +0 -74
  194. package/src/types/DataFormatterGrid.ts +0 -68
  195. package/src/types/DataFormatterMultiGrid.ts +0 -45
  196. package/src/types/DataFormatterMultiValue.ts +0 -24
  197. package/src/types/DataFormatterRelationship.ts +0 -26
  198. package/src/types/DataFormatterSeries.ts +0 -20
  199. package/src/types/DataFormatterTree.ts +0 -12
  200. package/src/types/DataGrid.ts +0 -11
  201. package/src/types/DataMultiGrid.ts +0 -7
  202. package/src/types/DataMultiValue.ts +0 -12
  203. package/src/types/DataRelationship.ts +0 -28
  204. package/src/types/DataSeries.ts +0 -11
  205. package/src/types/DataTree.ts +0 -20
  206. package/src/types/Event.ts +0 -153
  207. package/src/types/Layout.ts +0 -12
  208. package/src/types/Padding.ts +0 -6
  209. package/src/types/Plugin.ts +0 -60
  210. package/src/types/TransformData.ts +0 -8
  211. package/src/types/index.ts +0 -37
  212. /package/dist/src/{multiValue → utils}/multiValueObservables.d.ts +0 -0
  213. /package/dist/src/{relationship → utils}/relationshipObservables.d.ts +0 -0
  214. /package/src/{multiValue → utils}/multiValueObservables.ts +0 -0
  215. /package/src/{relationship → utils}/relationshipObservables.ts +0 -0
@@ -1,203 +1,220 @@
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
- ChartType,
14
- ChartParams,
15
- ComputedDataTypeMap,
16
- ComputedDatumTypeMap,
17
- DataFormatterTypeMap,
18
- EventTypeMap,
19
- HighlightTarget,
20
- Layout,
21
- TransformData } from '../types'
22
-
23
- // interface DatumUnknown {
24
- // value: number | null
25
- // id: string
26
- // // label: string
27
- // seriesLabel?: string // 要符合每一種computedData所以不一定會有seriesLabel
28
- // groupLabel?: string // 要符合每一種computedData所以不一定會有groupLabel
29
- // }
30
-
31
- // 通用 highlight Observable
32
- export const highlightObservable = <T extends ChartType, D>({ datumList$, fullChartParams$, event$ }: {
33
- datumList$: Observable<D[]>
34
- fullChartParams$: Observable<ChartParams>
35
- event$: Subject<EventTypeMap<T>>
36
- }): Observable<D[]> => {
37
- const destroy$ = new Subject()
38
-
39
- // 預設的highlight
40
- const highlightDefault$ = fullChartParams$.pipe(
41
- takeUntil(destroy$),
42
- map(d => {
43
- return {
44
- id: null,
45
- seriesLabel: null,
46
- groupLabel: null,
47
- categoryLabel: null,
48
- highlightDefault: d.highlightDefault
49
- }
50
- }),
51
- distinctUntilChanged()
52
- )
53
-
54
- // 事件觸發的highlight
55
- const highlightMouseover$ = event$.pipe(
56
- takeUntil(destroy$),
57
- // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
58
- filter(d => d.eventName === 'mouseover'),
59
- // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
60
- map(d => {
61
- return d.datum
62
- ? {
63
- id: (d.datum as any).id,
64
- seriesLabel: (d.datum as any).seriesLabel,
65
- groupLabel: (d.datum as any).groupLabel,
66
- categoryLabel: (d.datum as any).categoryLabel,
67
- highlightDefault: null
68
- }
69
- : {
70
- id: null,
71
- seriesLabel: null,
72
- groupLabel: null,
73
- categoryLabel: null,
74
- highlightDefault: null
75
- }
76
- })
77
- )
78
- const highlightMouseout$ = event$.pipe(
79
- takeUntil(destroy$),
80
- filter(d => d.eventName === 'mouseout'),
81
- // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
82
- // map(d => {
83
- // return { id: '', label: '' }
84
- // })
85
- switchMap(d => highlightDefault$)
86
- )
87
-
88
- function getDatumIds (datumList: ComputedDatumTypeMap<T>[], id: string | null) {
89
- const datum = datumList.find(d => d.id === id)
90
- return datum ? [datum] : []
91
- }
92
-
93
- function getSeriesIds (datumList: ComputedDatumTypeMap<T>[], seriesLabel: string | null) {
94
- return seriesLabel == null
95
- ? []
96
- : datumList.filter(d => (d as ComputedDatumTypeMap<"series">).seriesLabel === seriesLabel)
97
- }
98
-
99
- function getGroupIds (datumList: ComputedDatumTypeMap<T>[], groupLabel: string | null) {
100
- return groupLabel == null
101
- ? []
102
- : datumList.filter(d => (d as ComputedDatumTypeMap<"grid">).groupLabel === groupLabel)
103
- }
104
-
105
- function getCategoryIds (datumList: ComputedDatumTypeMap<T>[], categoryLabel: string | null) {
106
- return categoryLabel == null
107
- ? []
108
- : datumList.filter(d => (d as ComputedDatumTypeMap<"multiValue" | "relationship" | "tree">).categoryLabel === categoryLabel)
109
- }
110
-
111
- return new Observable<D[]>(subscriber => {
112
- combineLatest({
113
- target: merge(highlightMouseover$, highlightMouseout$, highlightDefault$),
114
- datumList: datumList$,
115
- fullChartParams: fullChartParams$,
116
- }).pipe(
117
- takeUntil(destroy$),
118
- switchMap(async d => d)
119
- ).subscribe(data => {
120
- let datumList: ComputedDatumTypeMap<T>[] = []
121
- if (data.fullChartParams.highlightTarget === 'datum') {
122
- datumList = getDatumIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.id)
123
- } else if (data.fullChartParams.highlightTarget === 'series') {
124
- datumList = getSeriesIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.seriesLabel)
125
- } else if (data.fullChartParams.highlightTarget === 'group') {
126
- datumList = getGroupIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.groupLabel)
127
- } else if (data.fullChartParams.highlightTarget === 'category') {
128
- datumList = getCategoryIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.categoryLabel)
129
- }
130
- subscriber.next(datumList as D[])
131
- })
132
-
133
- return function unsubscribe () {
134
- destroy$.next(undefined)
135
- }
136
- })
137
- }
138
-
139
- export const seriesDataMapObservable = <DatumType extends ComputedDatumTypeMap<'series' | 'grid'>>({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
140
- return datumList$.pipe(
141
- map(data => {
142
- const SeriesDataMap: Map<string, DatumType[]> = new Map()
143
- data.forEach(d => {
144
- const seriesData = SeriesDataMap.get(d.seriesLabel) ?? []
145
- seriesData.push(d)
146
- SeriesDataMap.set(d.seriesLabel, seriesData)
147
- })
148
- return SeriesDataMap
149
- })
150
- )
151
- }
152
-
153
- export const groupDataMapObservable = <DatumType extends ComputedDatumTypeMap<'grid'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
154
- return datumList$.pipe(
155
- map(data => {
156
- const GroupDataMap: Map<string, DatumType[]> = new Map()
157
- data.forEach(d => {
158
- const groupData = GroupDataMap.get(d.groupLabel) ?? []
159
- groupData.push(d)
160
- GroupDataMap.set(d.groupLabel, groupData)
161
- })
162
- return GroupDataMap
163
- })
164
- )
165
- }
166
-
167
- export const categoryDataMapObservable = <DatumType extends ComputedDatumTypeMap<'multiValue' | 'relationship' | 'tree'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
168
- return datumList$.pipe(
169
- map(data => {
170
- const GroupDataMap: Map<string, DatumType[]> = new Map()
171
- data
172
- .filter(d => d.categoryLabel != null)
173
- .forEach(d => {
174
- const groupData = GroupDataMap.get(d.categoryLabel) ?? []
175
- groupData.push(d)
176
- GroupDataMap.set(d.categoryLabel, groupData)
177
- })
178
- return GroupDataMap
179
- })
180
- )
181
- }
182
-
183
- export const textSizePxObservable = (chartParams$: Observable<ChartParams>) => {
184
- return chartParams$.pipe(
185
- map(d => d.styles.textSize),
186
- distinctUntilChanged(),
187
- map(data => {
188
- let value = NaN
189
- if (typeof data === 'string') {
190
- if (data.includes('rem')) {
191
- const rootFontSizePx = parseFloat(getComputedStyle(document.documentElement).fontSize)
192
- const num = parseFloat(data)
193
- value = num * rootFontSizePx
194
- } else if (data.includes('px')) {
195
- value = parseFloat(data)
196
- }
197
- } else if (typeof data === 'number') {
198
- return data
199
- }
200
- return value ? value : 14 // default
201
- })
202
- )
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
+ ChartType,
14
+ ChartParams,
15
+ ComputedDatumBase,
16
+ ComputedDataTypeMap,
17
+ ComputedDatumTypeMap,
18
+ DataFormatterTypeMap,
19
+ EventTypeMap,
20
+ HighlightTarget,
21
+ Layout,
22
+ TransformData } from '../../lib/core-types'
23
+
24
+ // interface DatumUnknown {
25
+ // value: number | null
26
+ // id: string
27
+ // // label: string
28
+ // seriesLabel?: string // 要符合每一種computedData所以不一定會有seriesLabel
29
+ // groupLabel?: string // 要符合每一種computedData所以不一定會有groupLabel
30
+ // }
31
+
32
+ export function resizeObservable(elem: HTMLElement | Element): Observable<DOMRectReadOnly> {
33
+ return new Observable(subscriber => {
34
+ const ro = new ResizeObserver(entries => {
35
+ const entry = entries[0]
36
+ if (entry && entry.contentRect) {
37
+ subscriber.next(entry.contentRect)
38
+ }
39
+ })
40
+
41
+ ro.observe(elem)
42
+ return function unsubscribe() {
43
+ ro.unobserve(elem)
44
+ }
45
+ })
46
+ }
47
+
48
+ // 通用 highlight Observable
49
+ export const highlightObservable = <T extends ChartType, D>({ datumList$, fullChartParams$, event$ }: {
50
+ datumList$: Observable<D[]>
51
+ fullChartParams$: Observable<ChartParams>
52
+ event$: Subject<EventTypeMap<T>>
53
+ }): Observable<D[]> => {
54
+ const destroy$ = new Subject()
55
+
56
+ // 預設的highlight
57
+ const highlightDefault$ = fullChartParams$.pipe(
58
+ takeUntil(destroy$),
59
+ map(d => {
60
+ return {
61
+ id: null,
62
+ seriesLabel: null,
63
+ groupLabel: null,
64
+ categoryLabel: null,
65
+ highlightDefault: d.highlightDefault
66
+ }
67
+ }),
68
+ distinctUntilChanged()
69
+ )
70
+
71
+ // 事件觸發的highlight
72
+ const highlightMouseover$ = event$.pipe(
73
+ takeUntil(destroy$),
74
+ // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
75
+ filter(d => d.eventName === 'mouseover'),
76
+ // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
77
+ map(d => {
78
+ return (d as any).datum
79
+ ? {
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,
84
+ highlightDefault: null
85
+ }
86
+ : {
87
+ id: null,
88
+ seriesLabel: null,
89
+ groupLabel: null,
90
+ categoryLabel: null,
91
+ highlightDefault: null
92
+ }
93
+ })
94
+ )
95
+ const highlightMouseout$ = event$.pipe(
96
+ takeUntil(destroy$),
97
+ filter(d => d.eventName === 'mouseout'),
98
+ // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
99
+ // map(d => {
100
+ // return { id: '', label: '' }
101
+ // })
102
+ switchMap(d => highlightDefault$)
103
+ )
104
+
105
+ function getDatumIds (datumList: ComputedDatumTypeMap<T>[], id: string | null) {
106
+ const datum = datumList.find(d => (d as ComputedDatumBase).id === id)
107
+ return datum ? [datum] : []
108
+ }
109
+
110
+ function getSeriesIds (datumList: ComputedDatumTypeMap<T>[], seriesLabel: string | null) {
111
+ return seriesLabel == null
112
+ ? []
113
+ : datumList.filter(d => (d as ComputedDatumTypeMap<"series">).seriesLabel === seriesLabel)
114
+ }
115
+
116
+ function getGroupIds (datumList: ComputedDatumTypeMap<T>[], groupLabel: string | null) {
117
+ return groupLabel == null
118
+ ? []
119
+ : datumList.filter(d => (d as ComputedDatumTypeMap<"grid">).groupLabel === groupLabel)
120
+ }
121
+
122
+ function getCategoryIds (datumList: ComputedDatumTypeMap<T>[], categoryLabel: string | null) {
123
+ return categoryLabel == null
124
+ ? []
125
+ : datumList.filter(d => (d as ComputedDatumTypeMap<"multiValue" | "relationship" | "tree">).categoryLabel === categoryLabel)
126
+ }
127
+
128
+ return new Observable<D[]>(subscriber => {
129
+ combineLatest({
130
+ target: merge(highlightMouseover$, highlightMouseout$, highlightDefault$),
131
+ datumList: datumList$,
132
+ fullChartParams: fullChartParams$,
133
+ }).pipe(
134
+ takeUntil(destroy$),
135
+ switchMap(async d => d)
136
+ ).subscribe(data => {
137
+ let datumList: ComputedDatumTypeMap<T>[] = []
138
+ if (data.fullChartParams.highlightTarget === 'datum') {
139
+ datumList = getDatumIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.id)
140
+ } else if (data.fullChartParams.highlightTarget === 'series') {
141
+ datumList = getSeriesIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.seriesLabel)
142
+ } else if (data.fullChartParams.highlightTarget === 'group') {
143
+ datumList = getGroupIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.groupLabel)
144
+ } else if (data.fullChartParams.highlightTarget === 'category') {
145
+ datumList = getCategoryIds(data.datumList as ComputedDatumTypeMap<T>[], data.target.categoryLabel)
146
+ }
147
+ subscriber.next(datumList as D[])
148
+ })
149
+
150
+ return function unsubscribe () {
151
+ destroy$.next(undefined)
152
+ }
153
+ })
154
+ }
155
+
156
+ export const seriesDataMapObservable = <DatumType extends ComputedDatumTypeMap<'series' | 'grid'>>({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
157
+ return datumList$.pipe(
158
+ map(data => {
159
+ const SeriesDataMap: Map<string, DatumType[]> = new Map()
160
+ data.forEach(d => {
161
+ const seriesData = SeriesDataMap.get(d.seriesLabel) ?? []
162
+ seriesData.push(d)
163
+ SeriesDataMap.set(d.seriesLabel, seriesData)
164
+ })
165
+ return SeriesDataMap
166
+ })
167
+ )
168
+ }
169
+
170
+ export const groupDataMapObservable = <DatumType extends ComputedDatumTypeMap<'grid'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
171
+ return datumList$.pipe(
172
+ map(data => {
173
+ const GroupDataMap: Map<string, DatumType[]> = new Map()
174
+ data.forEach(d => {
175
+ const groupData = GroupDataMap.get(d.groupLabel) ?? []
176
+ groupData.push(d)
177
+ GroupDataMap.set(d.groupLabel, groupData)
178
+ })
179
+ return GroupDataMap
180
+ })
181
+ )
182
+ }
183
+
184
+ export const categoryDataMapObservable = <DatumType extends ComputedDatumTypeMap<'multiValue' | 'relationship' | 'tree'>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
185
+ return datumList$.pipe(
186
+ map(data => {
187
+ const GroupDataMap: Map<string, DatumType[]> = new Map()
188
+ data
189
+ .filter(d => d.categoryLabel != null)
190
+ .forEach(d => {
191
+ const groupData = GroupDataMap.get(d.categoryLabel) ?? []
192
+ groupData.push(d)
193
+ GroupDataMap.set(d.categoryLabel, groupData)
194
+ })
195
+ return GroupDataMap
196
+ })
197
+ )
198
+ }
199
+
200
+ export const textSizePxObservable = (chartParams$: Observable<ChartParams>) => {
201
+ return chartParams$.pipe(
202
+ map(d => d.styles.textSize),
203
+ distinctUntilChanged(),
204
+ map(data => {
205
+ let value = NaN
206
+ if (typeof data === 'string') {
207
+ if (data.includes('rem')) {
208
+ const rootFontSizePx = parseFloat(getComputedStyle(document.documentElement).fontSize)
209
+ const num = parseFloat(data)
210
+ value = num * rootFontSizePx
211
+ } else if (data.includes('px')) {
212
+ value = parseFloat(data)
213
+ }
214
+ } else if (typeof data === 'number') {
215
+ return data
216
+ }
217
+ return value ? value : 14 // default
218
+ })
219
+ )
203
220
  }