@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.
- package/.gitignore +23 -0
- package/LICENSE +201 -0
- package/dist/orbcharts-core.es.js +5096 -0
- package/dist/orbcharts-core.umd.js +3 -0
- package/dist/src/AbstractChart.d.ts +17 -0
- package/dist/src/GridChart.d.ts +6 -0
- package/dist/src/MultiGridChart.d.ts +6 -0
- package/dist/src/MultiValueChart.d.ts +6 -0
- package/dist/src/RelationshipChart.d.ts +6 -0
- package/dist/src/SeriesChart.d.ts +6 -0
- package/dist/src/TreeChart.d.ts +6 -0
- package/dist/src/base/createBaseChart.d.ts +3 -0
- package/dist/src/base/createBasePlugin.d.ts +3 -0
- package/dist/src/defaults.d.ts +37 -0
- package/dist/src/defineGridPlugin.d.ts +1 -0
- package/dist/src/defineMultiGridPlugin.d.ts +1 -0
- package/dist/src/defineMultiValuePlugin.d.ts +1 -0
- package/dist/src/defineNoneDataPlugin.d.ts +1 -0
- package/dist/src/defineRelationshipPlugin.d.ts +1 -0
- package/dist/src/defineSeriesPlugin.d.ts +1 -0
- package/dist/src/defineTreePlugin.d.ts +1 -0
- package/dist/src/grid/computeGridData.d.ts +3 -0
- package/dist/src/grid/createGridContextObserver.d.ts +3 -0
- package/dist/src/grid/gridObservables.d.ts +25 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/multiGrid/computeMultiGridData.d.ts +3 -0
- package/dist/src/multiGrid/createMultiGridContextObserver.d.ts +3 -0
- package/dist/src/multiGrid/multiGridObservables.d.ts +0 -0
- package/dist/src/multiValue/computeMultiValueData.d.ts +3 -0
- package/dist/src/multiValue/createMultiValueContextObserver.d.ts +3 -0
- package/dist/src/multiValue/multiValueObservables.d.ts +0 -0
- package/dist/src/relationship/computeRelationshipData.d.ts +3 -0
- package/dist/src/relationship/createRelationshipContextObserver.d.ts +3 -0
- package/dist/src/relationship/relationshipObservables.d.ts +0 -0
- package/dist/src/series/computeSeriesData.d.ts +3 -0
- package/dist/src/series/createSeriesContextObserver.d.ts +3 -0
- package/dist/src/series/seriesObservables.d.ts +8 -0
- package/dist/src/tree/computeTreeData.d.ts +3 -0
- package/dist/src/tree/createTreeContextObserver.d.ts +3 -0
- package/dist/src/tree/treeObservables.d.ts +0 -0
- package/dist/src/types/Axis.d.ts +1 -0
- package/dist/src/types/Chart.d.ts +41 -0
- package/dist/src/types/ChartParams.d.ts +36 -0
- package/dist/src/types/ComputedData.d.ts +28 -0
- package/dist/src/types/ComputedDataGrid.d.ts +10 -0
- package/dist/src/types/ComputedDataMultiGrid.d.ts +3 -0
- package/dist/src/types/ComputedDataMultiValue.d.ts +6 -0
- package/dist/src/types/ComputedDataRelationship.d.ts +18 -0
- package/dist/src/types/ComputedDataSeries.d.ts +6 -0
- package/dist/src/types/ComputedDataTree.d.ts +7 -0
- package/dist/src/types/ContextObserver.d.ts +28 -0
- package/dist/src/types/ContextObserverGrid.d.ts +18 -0
- package/dist/src/types/ContextObserverMultiGrid.d.ts +4 -0
- package/dist/src/types/ContextObserverMultiValue.d.ts +4 -0
- package/dist/src/types/ContextObserverRelationship.d.ts +4 -0
- package/dist/src/types/ContextObserverSeries.d.ts +8 -0
- package/dist/src/types/ContextObserverTree.d.ts +4 -0
- package/dist/src/types/ContextSubject.d.ts +15 -0
- package/dist/src/types/Data.d.ts +19 -0
- package/dist/src/types/DataFormatter.d.ts +40 -0
- package/dist/src/types/DataFormatterGrid.d.ts +20 -0
- package/dist/src/types/DataFormatterMultiGrid.d.ts +16 -0
- package/dist/src/types/DataFormatterMultiValue.d.ts +13 -0
- package/dist/src/types/DataFormatterRelationship.d.ts +5 -0
- package/dist/src/types/DataFormatterSeries.d.ts +10 -0
- package/dist/src/types/DataFormatterTree.d.ts +5 -0
- package/dist/src/types/DataGrid.d.ts +6 -0
- package/dist/src/types/DataMultiGrid.d.ts +6 -0
- package/dist/src/types/DataMultiValue.d.ts +6 -0
- package/dist/src/types/DataRelationship.d.ts +20 -0
- package/dist/src/types/DataSeries.d.ts +6 -0
- package/dist/src/types/DataTree.d.ts +13 -0
- package/dist/src/types/Event.d.ts +64 -0
- package/dist/src/types/Layout.d.ts +8 -0
- package/dist/src/types/Padding.d.ts +6 -0
- package/dist/src/types/Plugin.d.ts +37 -0
- package/dist/src/types/TransformData.d.ts +8 -0
- package/dist/src/types/index.d.ts +37 -0
- package/dist/src/utils/commonUtils.d.ts +8 -0
- package/dist/src/utils/d3Utils.d.ts +25 -0
- package/dist/src/utils/index.d.ts +4 -0
- package/dist/src/utils/observables.d.ts +14 -0
- package/dist/src/utils/orbchartsUtils.d.ts +20 -0
- package/dist/vite.config.d.ts +2 -0
- package/package.json +40 -0
- package/src/AbstractChart.ts +48 -0
- package/src/GridChart.ts +21 -0
- package/src/MultiGridChart.ts +21 -0
- package/src/MultiValueChart.ts +21 -0
- package/src/RelationshipChart.ts +21 -0
- package/src/SeriesChart.ts +21 -0
- package/src/TreeChart.ts +21 -0
- package/src/base/createBaseChart.ts +329 -0
- package/src/base/createBasePlugin.ts +89 -0
- package/src/defaults.ts +229 -0
- package/src/defineGridPlugin.ts +3 -0
- package/src/defineMultiGridPlugin.ts +3 -0
- package/src/defineMultiValuePlugin.ts +3 -0
- package/src/defineNoneDataPlugin.ts +4 -0
- package/src/defineRelationshipPlugin.ts +3 -0
- package/src/defineSeriesPlugin.ts +3 -0
- package/src/defineTreePlugin.ts +3 -0
- package/src/grid/computeGridData.ts +192 -0
- package/src/grid/createGridContextObserver.ts +91 -0
- package/src/grid/gridObservables.ts +359 -0
- package/src/index.ts +21 -0
- package/src/multiGrid/computeMultiGridData.ts +48 -0
- package/src/multiGrid/createMultiGridContextObserver.ts +12 -0
- package/src/multiGrid/multiGridObservables.ts +0 -0
- package/src/multiValue/computeMultiValueData.ts +127 -0
- package/src/multiValue/createMultiValueContextObserver.ts +12 -0
- package/src/multiValue/multiValueObservables.ts +0 -0
- package/src/relationship/computeRelationshipData.ts +101 -0
- package/src/relationship/createRelationshipContextObserver.ts +12 -0
- package/src/relationship/relationshipObservables.ts +0 -0
- package/src/series/computeSeriesData.ts +154 -0
- package/src/series/createSeriesContextObserver.ts +33 -0
- package/src/series/seriesObservables.ts +23 -0
- package/src/tree/computeTreeData.ts +104 -0
- package/src/tree/createTreeContextObserver.ts +12 -0
- package/src/tree/treeObservables.ts +0 -0
- package/src/types/Axis.ts +1 -0
- package/src/types/Chart.ts +46 -0
- package/src/types/ChartParams.ts +50 -0
- package/src/types/ComputedData.ts +66 -0
- package/src/types/ComputedDataGrid.ts +12 -0
- package/src/types/ComputedDataMultiGrid.ts +3 -0
- package/src/types/ComputedDataMultiValue.ts +10 -0
- package/src/types/ComputedDataRelationship.ts +20 -0
- package/src/types/ComputedDataSeries.ts +8 -0
- package/src/types/ComputedDataTree.ts +20 -0
- package/src/types/ContextObserver.ts +38 -0
- package/src/types/ContextObserverGrid.ts +16 -0
- package/src/types/ContextObserverMultiGrid.ts +5 -0
- package/src/types/ContextObserverMultiValue.ts +5 -0
- package/src/types/ContextObserverRelationship.ts +5 -0
- package/src/types/ContextObserverSeries.ts +8 -0
- package/src/types/ContextObserverTree.ts +5 -0
- package/src/types/ContextSubject.ts +18 -0
- package/src/types/Data.ts +45 -0
- package/src/types/DataFormatter.ts +99 -0
- package/src/types/DataFormatterGrid.ts +40 -0
- package/src/types/DataFormatterMultiGrid.ts +23 -0
- package/src/types/DataFormatterMultiValue.ts +19 -0
- package/src/types/DataFormatterRelationship.ts +23 -0
- package/src/types/DataFormatterSeries.ts +26 -0
- package/src/types/DataFormatterTree.ts +10 -0
- package/src/types/DataGrid.ts +11 -0
- package/src/types/DataMultiGrid.ts +7 -0
- package/src/types/DataMultiValue.ts +11 -0
- package/src/types/DataRelationship.ts +27 -0
- package/src/types/DataSeries.ts +11 -0
- package/src/types/DataTree.ts +18 -0
- package/src/types/Event.ts +114 -0
- package/src/types/Layout.ts +12 -0
- package/src/types/Padding.ts +6 -0
- package/src/types/Plugin.ts +60 -0
- package/src/types/TransformData.ts +8 -0
- package/src/types/index.ts +37 -0
- package/src/utils/commonUtils.ts +50 -0
- package/src/utils/d3Utils.ts +87 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/observables.ts +198 -0
- package/src/utils/orbchartsUtils.ts +150 -0
- package/tsconfig.json +14 -0
- 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,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
|
+
})
|