@orbcharts/core 3.0.0-alpha.21

Sign up to get free protection for your applications and to get access to all the features.
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,50 @@
1
+ // import * as d3 from 'd3'
2
+
3
+ // 是否為物件
4
+ export function isObject(variable: any) {
5
+ return Object.prototype.toString.call(variable) === "[object Object]";
6
+ }
7
+
8
+ // 是否為function
9
+ export function isFunction(fn: any) {
10
+ return !!fn && !fn.nodename && fn.constructor != String && fn.constructor != RegExp && fn.constructor != Array && /function/i.test(fn + "");
11
+ }
12
+
13
+ // 將可選的參數和預設值合併
14
+ export function mergeOptionsWithDefault<Options extends { [key: string]: any; }> (options: {[key: string]: any}, defaultOptions: Options): Options {
15
+ if (isObject(options) === false || isObject(defaultOptions) === false) {
16
+ return Object.assign({}, defaultOptions)
17
+ }
18
+ const mergeObjColumns = (_options: {[key: string]: any}, _defaultOptions: {[key: string]: any}) => {
19
+ const obj: Options = (Object.assign({}, _defaultOptions) as any)
20
+ for (let key of Object.keys(_options)) {
21
+ if ((key in _defaultOptions) == false) {
22
+ continue
23
+ }
24
+ let objValue: any = undefined
25
+ // 下一層的object
26
+ if (isObject(_options[key]) && isObject(_defaultOptions[key])) {
27
+ objValue = mergeObjColumns(_options[key], _defaultOptions[key])
28
+ obj[key as keyof Options] = objValue
29
+ }
30
+ // 不是object直接賦值
31
+ else {
32
+ obj[key as keyof Options] = _options[key]
33
+ }
34
+ }
35
+ return obj
36
+ }
37
+
38
+ return mergeObjColumns(options, defaultOptions)
39
+ }
40
+
41
+ // 加上千分位 ,
42
+ export function formatCommaNumber (num = 0): string {
43
+ try {
44
+ let parts = num.toString().split('.');
45
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
46
+ return parts.join('.');
47
+ } catch (e: any) {
48
+ console.error(e)
49
+ }
50
+ }
@@ -0,0 +1,87 @@
1
+ import * as d3 from 'd3'
2
+ import { DATA_FORMATTER_VALUE_AXIS } from '../defaults'
3
+
4
+ // scaleLinear - 連續資料對應到比較尺座標上
5
+ export const createAxisLinearScale = ({
6
+ maxValue = 1,
7
+ minValue = 0,
8
+ axisWidth,
9
+ scaleDomain = DATA_FORMATTER_VALUE_AXIS.scaleDomain,
10
+ scaleRange = DATA_FORMATTER_VALUE_AXIS.scaleRange,
11
+ }: {
12
+ maxValue: number
13
+ minValue: number
14
+ axisWidth: number
15
+ scaleDomain: [number | 'auto', number | 'auto']
16
+ scaleRange: [number, number] // 0-1
17
+ }) => {
18
+
19
+ const domainMin: number | 'auto' = scaleDomain[0] ?? DATA_FORMATTER_VALUE_AXIS.scaleDomain[0]
20
+ const domainMax: number | 'auto' = scaleDomain[1] ?? DATA_FORMATTER_VALUE_AXIS.scaleDomain[1]
21
+ const rangeMin: number = scaleRange[0] ?? DATA_FORMATTER_VALUE_AXIS.scaleRange[0]
22
+ const rangeMax: number = scaleRange[1] ?? DATA_FORMATTER_VALUE_AXIS.scaleRange[1]
23
+
24
+ // const _minValue = domainMin === 'auto' ? minValue : domainMin
25
+ // const domainMinValue: number = maxValue - (maxValue - _minValue) / (1 - rangeMin)
26
+ // const _maxValue = domainMax === 'auto' ? maxValue : domainMax
27
+ // const domainMaxValue: number = _maxValue / rangeMax
28
+
29
+ // return d3.scaleLinear()
30
+ // .domain([domainMinValue, domainMaxValue])
31
+ // .range([0, axisWidth])
32
+
33
+ const domainMinValue = domainMin === 'auto' ? minValue : domainMin
34
+ const domainMaxValue = domainMax === 'auto' ? maxValue : domainMax
35
+ let rangeMinValue = axisWidth * rangeMin
36
+ let rangeMaxValue = axisWidth * rangeMax
37
+ // if (padding > 0) {
38
+ // const stepAmount = maxValue - minValue + (padding * 2)
39
+ // const eachStepWidth = axisWidth / stepAmount
40
+ // const paddingWidth = eachStepWidth * padding
41
+ // rangeMinValue += paddingWidth
42
+ // rangeMaxValue -= paddingWidth
43
+ // }
44
+
45
+ return d3.scaleLinear()
46
+ .domain([domainMinValue, domainMaxValue])
47
+ .range([rangeMinValue, rangeMaxValue])
48
+ }
49
+
50
+ // scalePoint - 非連續資料對應到比例尺座標上
51
+ export const createAxisPointScale = ({ axisLabels, axisWidth, padding = 0.5 }: {
52
+ axisLabels: string[]
53
+ axisWidth: number
54
+ padding?: number
55
+ // reverse?: boolean
56
+ }) => {
57
+ let range: [d3.NumberValue, d3.NumberValue] = [0, axisWidth]
58
+
59
+ return d3.scalePoint()
60
+ .domain(axisLabels)
61
+ .range(range)
62
+ .padding(padding)
63
+ }
64
+
65
+ // scaleQuantize - 比例尺座標對應非連續資料索引
66
+ export const createAxisQuantizeScale = ({ axisLabels, axisWidth, padding = 0.5, reverse = false }:{
67
+ axisLabels: string[] | Date[],
68
+ axisWidth: number
69
+ padding?: number
70
+ reverse?: boolean
71
+ }) => {
72
+ const rangePadding = 0
73
+
74
+ let range: number[] = axisLabels.map((d: string | Date, i: number) => i)
75
+ if (reverse) {
76
+ range.reverse()
77
+ }
78
+ // if (reverse) {
79
+ // range = axisLabels.map((d: string | Date, i: number) => axisLabels.length - 1 - i)
80
+ // } else {
81
+ // range = axisLabels.map((d: string | Date, i: number) => i)
82
+ // }
83
+
84
+ return d3.scaleQuantize<number>()
85
+ .domain([- rangePadding, axisWidth + rangePadding])
86
+ .range(range)
87
+ }
@@ -0,0 +1,4 @@
1
+ export * from './orbchartsUtils'
2
+ export * from './observables'
3
+ export * from './d3Utils'
4
+ export * from './commonUtils'
@@ -0,0 +1,198 @@
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
+ HighlightTarget,
19
+ Layout,
20
+ TransformData } from '../types'
21
+
22
+ // interface DatumUnknown {
23
+ // value: number | null
24
+ // id: string
25
+ // // label: string
26
+ // seriesLabel?: string // 要符合每一種computedData所以不一定會有seriesLabel
27
+ // groupLabel?: string // 要符合每一種computedData所以不一定會有groupLabel
28
+ // }
29
+
30
+ export const highlightObservable = ({ datumList$, fullChartParams$, event$ }: {
31
+ datumList$: Observable<ComputedDatumTypeMap<'series' | 'grid'>[]>
32
+ fullChartParams$: Observable<ChartParams>
33
+ event$: Subject<any>
34
+ }): Observable<string[]> => {
35
+ const destroy$ = new Subject()
36
+
37
+ // 預設的highlight
38
+ const highlightDefault$ = fullChartParams$.pipe(
39
+ takeUntil(destroy$),
40
+ map(d => {
41
+ return {
42
+ id: null,
43
+ seriesLabel: null,
44
+ groupLabel: null,
45
+ highlightDefault: d.highlightDefault
46
+ }
47
+ }),
48
+ distinctUntilChanged()
49
+ )
50
+
51
+ // 事件觸發的highlight
52
+ const highlightMouseover$ = event$.pipe(
53
+ takeUntil(destroy$),
54
+ filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove'),
55
+ // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
56
+ map(d => {
57
+ return d.datum
58
+ ? {
59
+ id: (d.datum as any).id,
60
+ seriesLabel: (d.datum as any).seriesLabel,
61
+ groupLabel: (d.datum as any).groupLabel,
62
+ highlightDefault: null
63
+ }
64
+ : {
65
+ id: null,
66
+ seriesLabel: null,
67
+ groupLabel: null,
68
+ highlightDefault: null
69
+ }
70
+ })
71
+ )
72
+ const highlightMouseout$ = event$.pipe(
73
+ takeUntil(destroy$),
74
+ filter(d => d.eventName === 'mouseout'),
75
+ // distinctUntilChanged((prev, current) => prev.eventName === current.eventName)
76
+ // map(d => {
77
+ // return { id: '', label: '' }
78
+ // })
79
+ switchMap(d => highlightDefault$)
80
+ )
81
+
82
+ const getHighlightIds = ({ data, id, seriesLabel, groupLabel, highlightDefault, target }: {
83
+ data: ComputedDatumTypeMap<'series' | 'grid'>[]
84
+ id: string | null
85
+ seriesLabel: string | null
86
+ groupLabel: string | null
87
+ highlightDefault: string | null
88
+ target: HighlightTarget
89
+ }) => {
90
+ let ids: string[] = []
91
+ // if (id) {
92
+ // ids.push(id)
93
+ // }
94
+ // if (label) {
95
+ // if (target === 'group') {
96
+ // const _ids = data.flat()
97
+ // .filter(d => {
98
+ // return d.groupLabel === label
99
+ // || d.label === label
100
+ // })
101
+ // .map(d => d.id)
102
+ // ids = ids.concat(_ids)
103
+ // } else if (target === 'series') {
104
+ // const _ids = data.flat()
105
+ // .filter(d => {
106
+ // return d.seriesLabel === label
107
+ // || d.label === label
108
+ // })
109
+ // .map(d => d.id)
110
+ // ids = ids.concat(_ids)
111
+ // }
112
+ // }
113
+ // 依highlightDefault找到id/seriesLabel/groupLabel
114
+ if (highlightDefault != null && highlightDefault != '') {
115
+ if (target === 'datum') {
116
+ id = highlightDefault
117
+ } else if (target === 'series') {
118
+ const datum = data.flat().find(d => d.id === highlightDefault || d.seriesLabel === highlightDefault)
119
+ seriesLabel = (datum && datum.seriesLabel) ? datum.seriesLabel : null
120
+ } else if (target === 'group') {
121
+ const datum = data.flat().find(d => d.id === highlightDefault || (d as ComputedDatumTypeMap<"grid">).groupLabel === highlightDefault)
122
+ groupLabel = (datum && (datum as ComputedDatumTypeMap<"grid">).groupLabel) ? (datum as ComputedDatumTypeMap<"grid">).groupLabel : null
123
+ }
124
+ }
125
+ if (target === 'datum' && id != null && id != '') {
126
+ ids.push(id)
127
+ } else if (target === 'series' && seriesLabel != null && seriesLabel != '') {
128
+ const _ids = data.flat()
129
+ .filter(d => {
130
+ return d.seriesLabel === seriesLabel
131
+ })
132
+ .map(d => d.id)
133
+ ids = ids.concat(_ids)
134
+ } else if (target === 'group' && groupLabel != null && groupLabel != '') {
135
+ const _ids = data.flat()
136
+ .filter(d => {
137
+ return (d as ComputedDatumTypeMap<"grid">).groupLabel === groupLabel
138
+ })
139
+ .map(d => d.id)
140
+ ids = ids.concat(_ids)
141
+ }
142
+
143
+ return ids
144
+ }
145
+
146
+ return new Observable<string[]>(subscriber => {
147
+ combineLatest({
148
+ target: merge(highlightMouseover$, highlightMouseout$, highlightDefault$),
149
+ datumList: datumList$,
150
+ fullChartParams: fullChartParams$,
151
+ }).pipe(
152
+ takeUntil(destroy$)
153
+ ).subscribe(data => {
154
+ const ids = getHighlightIds({
155
+ data: data.datumList,
156
+ id: data.target.id,
157
+ seriesLabel: data.target.seriesLabel,
158
+ groupLabel: data.target.groupLabel,
159
+ highlightDefault: data.target.highlightDefault,
160
+ target: data.fullChartParams.highlightTarget,
161
+ })
162
+ subscriber.next(ids)
163
+ })
164
+
165
+ return function unsubscribe () {
166
+ destroy$.next(undefined)
167
+ }
168
+ })
169
+ }
170
+
171
+ export const seriesDataMapObservable = <DatumType extends ComputedDatumTypeMap<ChartType>>({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
172
+ return datumList$.pipe(
173
+ map(data => {
174
+ const SeriesDataMap: Map<string, DatumType[]> = new Map()
175
+ data.forEach(d => {
176
+ const seriesData = SeriesDataMap.get((d as ComputedDatumTypeMap<'series' | 'grid'>).seriesLabel) ?? []
177
+ seriesData.push(d)
178
+ SeriesDataMap.set((d as ComputedDatumTypeMap<'series' | 'grid'>).seriesLabel, seriesData)
179
+ })
180
+ return SeriesDataMap
181
+ })
182
+ )
183
+ }
184
+
185
+ export const groupDataMapObservable = <DatumType extends ComputedDatumTypeMap<ChartType>> ({ datumList$ }: { datumList$: Observable<DatumType[]> }) => {
186
+ return datumList$.pipe(
187
+ map(data => {
188
+ const GroupDataMap: Map<string, DatumType[]> = new Map()
189
+ data.forEach(d => {
190
+ const groupData = GroupDataMap.get((d as ComputedDatumTypeMap<'grid'>).groupLabel) ?? []
191
+ groupData.push(d)
192
+ GroupDataMap.set((d as ComputedDatumTypeMap<'grid'>).groupLabel, groupData)
193
+ })
194
+ return GroupDataMap
195
+ })
196
+ )
197
+ }
198
+
@@ -0,0 +1,150 @@
1
+ import * as d3 from 'd3'
2
+ import type { DatumBase, DatumValue } from '../types/Data'
3
+ import type { DataSeries, DataSeriesDatum, DataSeriesValue } from '../types/DataSeries'
4
+ import type { DataGrid, DataGridDatum, DataGridValue } from '../types/DataGrid'
5
+ import type { DataMultiGrid } from '../types/DataMultiGrid'
6
+ import type { DataMultiValue, DataMultiValueDatum, DataMultiValueValue } from '../types/DataMultiValue'
7
+ import type { SeriesType, DataFormatterGrid } from '../types/DataFormatterGrid'
8
+ import { isObject } from './commonUtils'
9
+
10
+ export function formatValueToLabel (value: any, valueFormatter: string | ((text: d3.NumberValue) => string)) {
11
+ if (valueFormatter! instanceof Function == true) {
12
+ return (valueFormatter as ((text: d3.NumberValue) => string))(value)
13
+ }
14
+ return d3.format(valueFormatter as string)!(value)
15
+ }
16
+
17
+ export function createDefaultDatumId (type: string, levelOneIndex: number, levelTwoIndex: number) {
18
+ return `${type}_${levelOneIndex}_${levelTwoIndex}`
19
+ }
20
+
21
+ export function createDefaultSeriesLabel (type: string, seriesIndex: number) {
22
+ return `${type}_series${seriesIndex}`
23
+ }
24
+
25
+ export function createDefaultGroupLabel (type: string, groupIndex: number) {
26
+ return `${type}_group${groupIndex}`
27
+ }
28
+
29
+ export function createGridSeriesLabels (transposedDataGrid: DataGridDatum[][], dataFormatter: DataFormatterGrid) {
30
+ const labels = dataFormatter.grid.seriesType === 'row'
31
+ ? dataFormatter.grid.rowLabels
32
+ : dataFormatter.grid.columnLabels
33
+ return transposedDataGrid.map((_, rowIndex) => {
34
+ return labels[rowIndex] != null
35
+ ? labels[rowIndex]
36
+ : createDefaultSeriesLabel('grid', rowIndex)
37
+ })
38
+ }
39
+
40
+ export function createGridGroupLabels (transposedDataGrid: DataGridDatum[][], dataFormatter: DataFormatterGrid) {
41
+ if (transposedDataGrid[0] == null) {
42
+ return []
43
+ }
44
+ const labels = dataFormatter.grid.seriesType === 'row'
45
+ ? dataFormatter.grid.columnLabels
46
+ : dataFormatter.grid.rowLabels
47
+ return transposedDataGrid[0].map((_, columnLabels) => {
48
+ return labels[columnLabels] != null
49
+ ? labels[columnLabels]
50
+ : createDefaultGroupLabel('grid', columnLabels)
51
+ })
52
+ }
53
+
54
+ // 取得最小及最大值 - 數字陣列
55
+ export function getMinAndMax (data: number[]): [number, number] {
56
+ const defaultMinAndMax: [number, number] = [0, 0] // default
57
+ if (!data.length) {
58
+ return defaultMinAndMax
59
+ }
60
+ const minAndMax: [number, number] = data.reduce((prev, current) => {
61
+ // [min, max]
62
+ return [
63
+ current < prev[0] ? current : prev[0],
64
+ current > prev[1] ? current : prev[1]
65
+ ]
66
+ }, [data[0], data[0]])
67
+ return minAndMax
68
+ }
69
+
70
+ // 取得最小及最大值 - datum格式陣列資料
71
+ export function getMinAndMaxValue (data: DatumValue[]): [number, number] {
72
+ const arr = data
73
+ .filter(d => d != null && d.value != null)
74
+ .map(d => d.value )
75
+ return getMinAndMax(arr)
76
+ }
77
+
78
+ // 取得最小及最大值 - Series Data
79
+ export function getMinAndMaxSeries (data: DataSeries): [number, number] {
80
+ const flatData: (DataSeriesValue | DataSeriesDatum)[] = data[0] && Array.isArray((data as (DataSeriesValue | DataSeriesDatum)[][])[0])
81
+ ? data.flat()
82
+ : data as (DataSeriesValue | DataSeriesDatum)[]
83
+ const arr = flatData
84
+ .filter(d => (d == null || (isObject(d) && (d as DataSeriesDatum).value == null)) === false) // 過濾掉null &
85
+ .map(d => typeof d === 'number' ? d : d.value )
86
+ return getMinAndMax(arr)
87
+ }
88
+
89
+ // 取得最小及最大值 - Grid Data
90
+ export function getMinAndMaxGrid (data: DataGrid): [number, number] {
91
+ const flatData: (DataGridValue | DataGridDatum)[] = data.flat()
92
+ const arr = flatData
93
+ .filter(d => (d == null || (isObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
94
+ .map(d => typeof d === 'number' ? d : d.value )
95
+ return getMinAndMax(arr)
96
+ }
97
+
98
+ // 取得最小及最大值 - MultiGrid Data
99
+ export function getMinAndMaxMultiGrid (data: DataMultiGrid): [number, number] {
100
+ const flatData: (DataGridValue | DataGridDatum)[] = data.flat().flat()
101
+ const arr = flatData
102
+ .filter(d => (d == null || (isObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
103
+ .map(d => typeof d === 'number' ? d : d.value )
104
+ return getMinAndMax(arr)
105
+ }
106
+
107
+ // 取得最小及最大值 - MultiValue Data
108
+ export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number = 2): [number, number] {
109
+ const flatData: (DataMultiValueDatum | DataMultiValueValue)[] = data.flat().filter((d, i) => i == valueIndex)
110
+ const arr = flatData
111
+ .filter(d => (d == null || (isObject(d) && (d as DataMultiValueDatum).value == null)) === false) // 過濾掉null
112
+ .map(d => typeof d === 'number' ? d : d.value )
113
+ return getMinAndMax(arr)
114
+ }
115
+
116
+ // @Q@ 待處理
117
+ // // 取得最小及最大值 - Relationship Data
118
+ // export function getMinAndMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
119
+
120
+ // }
121
+
122
+ // @Q@ 待處理
123
+ // // 取得最小及最大值 - Tree Data
124
+ // export function getMinAndMaxTree (data: DataTree): [number, number] {
125
+
126
+ // }
127
+
128
+ // 轉置成seriesType為main的陣列格式
129
+ export function transposeData<T> (seriesType: SeriesType, data: T[][]): T[][] {
130
+ if (seriesType === 'row') {
131
+ return Object.assign([], data)
132
+ }
133
+ // 取得原始陣列的維度
134
+ const rows = data.length;
135
+ const cols = data.reduce((prev, current) => {
136
+ return Math.max(prev, current.length)
137
+ }, 0)
138
+
139
+ // 初始化轉換後的陣列
140
+ const transposedArray = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
141
+
142
+ // 遍歷原始陣列,進行轉換
143
+ for (let i = 0; i < rows; i++) {
144
+ for (let j = 0; j < cols; j++) {
145
+ transposedArray[j][i] = data[i][j]
146
+ }
147
+ }
148
+
149
+ return transposedArray
150
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "./dist/",
4
+ "sourceMap": true,
5
+ "noImplicitAny": true,
6
+ "module": "es6",
7
+ "target": "es5",
8
+ "jsx": "react",
9
+ "allowJs": true,
10
+ "moduleResolution": "node",
11
+ "allowSyntheticDefaultImports" : true,
12
+ "esModuleInterop" : true
13
+ }
14
+ }
package/vite.config.js ADDED
@@ -0,0 +1,45 @@
1
+ // import { fileURLToPath, URL } from 'node:url'
2
+
3
+ // import { resolve } from 'path'
4
+ import { defineConfig } from 'vite'
5
+ import dts from 'vite-plugin-dts'
6
+
7
+ const releaseConfig = {
8
+ plugins: [
9
+ dts({
10
+ insertTypesEntry: true
11
+ })
12
+ ],
13
+ compilerOptions: {
14
+ composite: true
15
+ },
16
+ build: {
17
+ lib: {
18
+ entry: "src/index.ts",
19
+ name: 'orbcharts-core',
20
+ formats: ["es", "umd"],
21
+ fileName: format => `orbcharts-core.${format}.js`
22
+ },
23
+ // rollupOptions: {
24
+ // input: {
25
+ // main: resolve(__dirname, "src/index.ts")
26
+ // },
27
+ // external: ['vue'],
28
+ // output: {
29
+ // assetFileNames: 'my-library.css',
30
+ // exports: "named",
31
+ // globals: {
32
+ // vue: 'Vue',
33
+ // },
34
+ // },
35
+ // },
36
+ }
37
+ }
38
+
39
+ export default defineConfig(({ command, mode }) => {
40
+ if (mode === 'release') {
41
+ return releaseConfig
42
+ } else {
43
+ return releaseConfig
44
+ }
45
+ })