@orbcharts/core 3.0.6 → 4.0.0-pre-alpha.0
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/LICENSE +200 -200
- package/dist/orbcharts-core.es.js +2795 -6591
- package/dist/orbcharts-core.umd.js +6 -6
- package/dist/src/OrbCharts.d.ts +18 -0
- package/dist/src/chart/createChart.d.ts +3 -0
- package/dist/src/chart/createGraphData.d.ts +3 -0
- package/dist/src/chart/createGridData.d.ts +3 -0
- package/dist/src/chart/createMultivariateData.d.ts +3 -0
- package/dist/src/chart/createSeriesData.d.ts +3 -0
- package/dist/src/chart/createTreeData.d.ts +3 -0
- package/dist/src/chart/defaults.d.ts +5 -0
- package/dist/src/defineCanvasLayer.d.ts +16 -0
- package/dist/src/defineCanvasPlugin.d.ts +22 -0
- package/dist/src/defineSVGLayer.d.ts +16 -0
- package/dist/src/defineSVGPlugin.d.ts +22 -0
- package/dist/src/index.d.ts +6 -14
- package/dist/src/layer/createLayer.d.ts +3 -0
- package/dist/src/plugin/createPlugin.d.ts +3 -0
- package/dist/src/test/createGraphData.test.d.ts +1 -0
- package/dist/src/test/createTreeData.test.d.ts +1 -0
- package/dist/src/test/simple-graph-test.d.ts +74 -0
- package/dist/src/test/simple-tree-test.d.ts +13 -0
- package/dist/src/types/Chart.d.ts +39 -0
- package/dist/src/types/ChartContext.d.ts +27 -0
- package/dist/src/types/Common.d.ts +3 -0
- package/dist/src/types/Encoding.d.ts +33 -0
- package/dist/src/types/Event.d.ts +12 -0
- package/dist/src/types/Layers.d.ts +55 -0
- package/dist/src/types/ModelData.d.ts +70 -0
- package/dist/src/types/Plugin.d.ts +39 -0
- package/dist/src/types/RawData.d.ts +18 -0
- package/dist/src/types/RenderData.d.ts +4 -0
- package/dist/src/types/Theme.d.ts +17 -0
- package/dist/src/types/Validator.d.ts +20 -0
- package/dist/src/types/index.d.ts +12 -0
- package/dist/src/utils/aggregateUtils.d.ts +37 -0
- package/dist/src/utils/colorUtils.d.ts +22 -0
- package/dist/src/utils/commonUtils.d.ts +3 -5
- package/dist/src/utils/dom-lifecycle.d.ts +37 -0
- package/dist/src/utils/dom.d.ts +6 -0
- package/dist/src/utils/index.d.ts +5 -1
- package/dist/src/utils/observables.d.ts +1 -25
- package/dist/src/utils/orbchartsUtils.d.ts +2 -53
- package/dist/src/utils/validator.d.ts +2 -2
- package/dist/test/aggregateTest.d.ts +1 -0
- package/package.json +59 -46
- package/src/OrbCharts.ts +35 -0
- package/src/chart/createChart.ts +997 -0
- package/src/chart/createGraphData.ts +391 -0
- package/src/chart/createGridData.ts +247 -0
- package/src/chart/createMultivariateData.ts +181 -0
- package/src/chart/createSeriesData.ts +297 -0
- package/src/chart/createTreeData.ts +344 -0
- package/src/chart/defaults.ts +100 -0
- package/src/defineCanvasLayer.ts +24 -0
- package/src/defineCanvasPlugin.ts +39 -0
- package/src/defineSVGLayer.ts +24 -0
- package/src/defineSVGPlugin.ts +39 -0
- package/src/index.ts +8 -20
- package/src/layer/createLayer.ts +138 -0
- package/src/plugin/createPlugin.ts +470 -0
- package/src/test/createGraphData.test.ts +103 -0
- package/src/test/createTreeData.test.ts +97 -0
- package/src/test/simple-graph-test.js +51 -0
- package/src/test/simple-tree-test.js +58 -0
- package/src/types/Chart.ts +62 -0
- package/src/types/ChartContext.ts +42 -0
- package/src/types/Common.ts +5 -0
- package/src/types/Encoding.ts +43 -0
- package/src/types/Event.ts +26 -0
- package/src/types/Layers.ts +93 -0
- package/src/types/ModelData.ts +95 -0
- package/src/types/Plugin.ts +98 -0
- package/src/types/RawData.ts +67 -0
- package/src/types/RenderData.ts +16 -0
- package/src/types/Theme.ts +21 -0
- package/src/types/Validator.ts +36 -0
- package/src/types/index.ts +12 -0
- package/src/utils/aggregateUtils.ts +99 -0
- package/src/utils/colorUtils.ts +63 -0
- package/src/utils/commonUtils.ts +56 -55
- package/src/utils/dom-lifecycle.ts +164 -0
- package/src/utils/dom.ts +55 -0
- package/src/utils/errorMessage.ts +40 -40
- package/src/utils/index.ts +8 -4
- package/src/utils/observables.ts +16 -308
- package/src/utils/orbchartsUtils.ts +9 -396
- package/src/utils/validator.ts +127 -126
- package/dist/lib/core-types.d.ts +0 -1
- package/dist/src/AbstractChart.d.ts +0 -19
- package/dist/src/GridChart.d.ts +0 -6
- package/dist/src/MultiGridChart.d.ts +0 -6
- package/dist/src/MultiValueChart.d.ts +0 -6
- package/dist/src/RelationshipChart.d.ts +0 -6
- package/dist/src/SeriesChart.d.ts +0 -6
- package/dist/src/TreeChart.d.ts +0 -6
- package/dist/src/base/createBaseChart.d.ts +0 -3
- package/dist/src/base/createBasePlugin.d.ts +0 -3
- package/dist/src/base/validators/chartOptionsValidator.d.ts +0 -3
- package/dist/src/base/validators/chartParamsValidator.d.ts +0 -3
- package/dist/src/base/validators/elementValidator.d.ts +0 -3
- package/dist/src/base/validators/pluginsValidator.d.ts +0 -3
- package/dist/src/defaults.d.ts +0 -25
- package/dist/src/defineGridPlugin.d.ts +0 -1
- package/dist/src/defineMultiGridPlugin.d.ts +0 -1
- package/dist/src/defineMultiValuePlugin.d.ts +0 -1
- package/dist/src/defineNoneDataPlugin.d.ts +0 -1
- package/dist/src/defineRelationshipPlugin.d.ts +0 -1
- package/dist/src/defineSeriesPlugin.d.ts +0 -1
- package/dist/src/defineTreePlugin.d.ts +0 -1
- package/dist/src/grid/computedDataFn.d.ts +0 -4
- package/dist/src/grid/contextObserverCallback.d.ts +0 -3
- package/dist/src/grid/dataFormatterValidator.d.ts +0 -3
- package/dist/src/grid/dataValidator.d.ts +0 -3
- package/dist/src/grid/gridObservables.d.ts +0 -64
- package/dist/src/multiGrid/computedDataFn.d.ts +0 -3
- package/dist/src/multiGrid/contextObserverCallback.d.ts +0 -3
- package/dist/src/multiGrid/dataFormatterValidator.d.ts +0 -3
- package/dist/src/multiGrid/dataValidator.d.ts +0 -3
- package/dist/src/multiGrid/multiGridObservables.d.ts +0 -16
- package/dist/src/multiValue/computedDataFn.d.ts +0 -3
- package/dist/src/multiValue/contextObserverCallback.d.ts +0 -3
- package/dist/src/multiValue/dataFormatterValidator.d.ts +0 -3
- package/dist/src/multiValue/dataValidator.d.ts +0 -3
- package/dist/src/multiValue/multiValueObservables.d.ts +0 -130
- package/dist/src/relationship/computedDataFn.d.ts +0 -3
- package/dist/src/relationship/contextObserverCallback.d.ts +0 -3
- package/dist/src/relationship/dataFormatterValidator.d.ts +0 -3
- package/dist/src/relationship/dataValidator.d.ts +0 -3
- package/dist/src/relationship/relationshipObservables.d.ts +0 -13
- package/dist/src/series/computedDataFn.d.ts +0 -3
- package/dist/src/series/contextObserverCallback.d.ts +0 -3
- package/dist/src/series/dataFormatterValidator.d.ts +0 -3
- package/dist/src/series/dataValidator.d.ts +0 -3
- package/dist/src/series/seriesObservables.d.ts +0 -37
- package/dist/src/tree/computedDataFn.d.ts +0 -3
- package/dist/src/tree/contextObserverCallback.d.ts +0 -3
- package/dist/src/tree/dataFormatterValidator.d.ts +0 -3
- package/dist/src/tree/dataValidator.d.ts +0 -3
- package/dist/src/tree/treeObservables.d.ts +0 -10
- package/dist/src/utils/d3Scale.d.ts +0 -28
- package/lib/core-types.ts +0 -7
- package/src/AbstractChart.ts +0 -57
- package/src/GridChart.ts +0 -25
- package/src/MultiGridChart.ts +0 -25
- package/src/MultiValueChart.ts +0 -25
- package/src/RelationshipChart.ts +0 -25
- package/src/SeriesChart.ts +0 -25
- package/src/TreeChart.ts +0 -25
- package/src/base/createBaseChart.ts +0 -524
- package/src/base/createBasePlugin.ts +0 -154
- package/src/base/validators/chartOptionsValidator.ts +0 -24
- package/src/base/validators/chartParamsValidator.ts +0 -134
- package/src/base/validators/elementValidator.ts +0 -14
- package/src/base/validators/pluginsValidator.ts +0 -15
- package/src/defaults.ts +0 -284
- package/src/defineGridPlugin.ts +0 -3
- package/src/defineMultiGridPlugin.ts +0 -3
- package/src/defineMultiValuePlugin.ts +0 -3
- package/src/defineNoneDataPlugin.ts +0 -4
- package/src/defineRelationshipPlugin.ts +0 -3
- package/src/defineSeriesPlugin.ts +0 -3
- package/src/defineTreePlugin.ts +0 -3
- package/src/grid/computedDataFn.ts +0 -129
- package/src/grid/contextObserverCallback.ts +0 -209
- package/src/grid/dataFormatterValidator.ts +0 -126
- package/src/grid/dataValidator.ts +0 -13
- package/src/grid/gridObservables.ts +0 -699
- package/src/multiGrid/computedDataFn.ts +0 -123
- package/src/multiGrid/contextObserverCallback.ts +0 -109
- package/src/multiGrid/dataFormatterValidator.ts +0 -121
- package/src/multiGrid/dataValidator.ts +0 -13
- package/src/multiGrid/multiGridObservables.ts +0 -367
- package/src/multiValue/computedDataFn.ts +0 -113
- package/src/multiValue/contextObserverCallback.ts +0 -328
- package/src/multiValue/dataFormatterValidator.ts +0 -95
- package/src/multiValue/dataValidator.ts +0 -13
- package/src/multiValue/multiValueObservables.ts +0 -865
- package/src/relationship/computedDataFn.ts +0 -159
- package/src/relationship/contextObserverCallback.ts +0 -80
- package/src/relationship/dataFormatterValidator.ts +0 -14
- package/src/relationship/dataValidator.ts +0 -14
- package/src/relationship/relationshipObservables.ts +0 -85
- package/src/series/computedDataFn.ts +0 -88
- package/src/series/contextObserverCallback.ts +0 -132
- package/src/series/dataFormatterValidator.ts +0 -47
- package/src/series/dataValidator.ts +0 -13
- package/src/series/seriesObservables.ts +0 -210
- package/src/tree/computedDataFn.ts +0 -129
- package/src/tree/contextObserverCallback.ts +0 -58
- package/src/tree/dataFormatterValidator.ts +0 -14
- package/src/tree/dataValidator.ts +0 -14
- package/src/tree/treeObservables.ts +0 -106
- package/src/utils/d3Scale.ts +0 -198
- package/tsconfig.base.json +0 -14
- package/tsconfig.json +0 -3
- package/vite-env.d.ts +0 -7
- package/vite.config.js +0 -23
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Observable, Subject } from 'rxjs'
|
|
2
|
+
import type {
|
|
3
|
+
DeepPartial,
|
|
4
|
+
LayerEntity,
|
|
5
|
+
ChartContext,
|
|
6
|
+
ExtendableContext
|
|
7
|
+
} from './index'
|
|
8
|
+
import { ValidatorResult } from '../types/Validator'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export interface PluginInfo {
|
|
12
|
+
id: string
|
|
13
|
+
name: string
|
|
14
|
+
elementType: 'svg' | 'canvas'
|
|
15
|
+
shownLayers: string[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// export interface PluginSetupProps<ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>> {
|
|
19
|
+
// context: ChartContext<ExtendContext>
|
|
20
|
+
// svg: SVGElement
|
|
21
|
+
// canvas: HTMLCanvasElement
|
|
22
|
+
// pluginParams$: Observable<PluginParams>
|
|
23
|
+
// }
|
|
24
|
+
|
|
25
|
+
// export interface SVGPluginSetupProps<ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>> {
|
|
26
|
+
// context: ChartContext<ExtendContext>
|
|
27
|
+
// svgG: SVGGElement
|
|
28
|
+
// pluginParams$: Observable<PluginParams>
|
|
29
|
+
// }
|
|
30
|
+
|
|
31
|
+
// export interface CanvasPluginSetupProps<ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>> {
|
|
32
|
+
// context: ChartContext<ExtendContext>
|
|
33
|
+
// canvas: HTMLCanvasElement
|
|
34
|
+
// pluginParams$: Observable<PluginParams>
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
// export type PluginSetupProps<ElementType extends 'svg' | 'canvas', ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>> =
|
|
38
|
+
// ElementType extends 'svg' ? SVGPluginSetupProps<ExtendContext, PluginParams> :
|
|
39
|
+
// ElementType extends 'canvas' ? CanvasPluginSetupProps<ExtendContext, PluginParams> :
|
|
40
|
+
// never
|
|
41
|
+
|
|
42
|
+
export interface PluginSetupProps<ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>> {
|
|
43
|
+
context: ChartContext<ExtendContext>
|
|
44
|
+
pluginParams$: Observable<PluginParams>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface DefinePluginConfig<ExtendContext extends ExtendableContext, PluginParams extends Record<string, any>, AllLayerParams extends Record<string, any>>{
|
|
48
|
+
name: string
|
|
49
|
+
defaultParams?: PluginParams
|
|
50
|
+
validator?: (params: DeepPartial<AllLayerParams | PluginParams>) => ValidatorResult
|
|
51
|
+
// { valid: boolean; errors?: string[] }
|
|
52
|
+
layers?: LayerEntity<ExtendContext, PluginParams, AllLayerParams[keyof AllLayerParams]>[]
|
|
53
|
+
// extendContext?: (context: Readonly<ChartContext>) => ExtendContext
|
|
54
|
+
setup?: (props: PluginSetupProps<ExtendContext, PluginParams>) => () => void
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// export interface CreatePlugin<PluginParams> {
|
|
58
|
+
// (config: DefinePluginConfig<PluginParams>): PluginEntity<PluginParams>
|
|
59
|
+
// }
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
export interface PluginEntity<ElementType extends 'svg' | 'canvas', PluginParams extends Record<string, any>, AllLayerParams extends Record<string, any>> {
|
|
63
|
+
readonly _name: string
|
|
64
|
+
readonly _elementType: ElementType
|
|
65
|
+
_getId: () => string
|
|
66
|
+
_setId: (id: string) => void
|
|
67
|
+
_injectContext(context: ChartContext<{}>): void
|
|
68
|
+
// layer visibility controls
|
|
69
|
+
show(names: (keyof AllLayerParams) | (keyof AllLayerParams)[]): void
|
|
70
|
+
showOnly(names: (keyof AllLayerParams) | (keyof AllLayerParams)[]): void
|
|
71
|
+
showAll(): void
|
|
72
|
+
hide(names: (keyof AllLayerParams) | (keyof AllLayerParams)[]): void
|
|
73
|
+
hideAll(): void
|
|
74
|
+
toggle(names: (keyof AllLayerParams) | (keyof AllLayerParams)[]): void
|
|
75
|
+
getShownLayerNames(): (keyof AllLayerParams)[]
|
|
76
|
+
// layer params
|
|
77
|
+
// setLayers(partial: DeepPartial<PluginParams>): void // deep-merge with default
|
|
78
|
+
updateParams(patch: DeepPartial<PluginParams | AllLayerParams>): void // deep-merge with previous
|
|
79
|
+
forceReplaceParams(full: PluginParams | AllLayerParams): void // replace(特殊需求,可節省效能)
|
|
80
|
+
getParams(): Readonly<PluginParams | AllLayerParams>
|
|
81
|
+
// layer<LayerName extends keyof PluginParams>(name: LayerName): {
|
|
82
|
+
// // set(partial: DeepPartial<PluginParams[LayerName]>): void // deep-merge with default 該 layer 的 params
|
|
83
|
+
// update(patch: DeepPartial<PluginParams[LayerName]>): void // deep-merge with previous 該 layer 的 params
|
|
84
|
+
// replace(full: PluginParams[LayerName]): void // replace(特殊需求,可節省效能)
|
|
85
|
+
// show(): void
|
|
86
|
+
// hide(): void
|
|
87
|
+
// toggle(): void
|
|
88
|
+
// }
|
|
89
|
+
|
|
90
|
+
destroy(): void
|
|
91
|
+
|
|
92
|
+
// outputs (observables)
|
|
93
|
+
// layers$: Observable<LayersConfig> // 各 layer 的有效參數(合併後)
|
|
94
|
+
// visibleLayerNames$: Observable<string[]> // 目前可見的 layer 清單(原 show$)
|
|
95
|
+
// event$: Observable<{ data: EventData; event: Event }> // 互動事件
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
// RawData -> ModelData (DataEndoding & ModelType) -> RenderData (Plugin)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export type RawData = RawDataColumn[] | RawDataColumn[][] // 二維陣列會轉化為多個dataset
|
|
8
|
+
|
|
9
|
+
// 可透過 DataEncoding 更改欄位名稱的預設欄位
|
|
10
|
+
export type DynamicDefaultRawDataFields = {
|
|
11
|
+
value?: number | null
|
|
12
|
+
x?: number | null // multivariate
|
|
13
|
+
y?: number | null // multivariate
|
|
14
|
+
z?: number | null // multivariate
|
|
15
|
+
dataset?: string
|
|
16
|
+
series?: string
|
|
17
|
+
category?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type RawDataColumn<DynamicFields extends Record<string, any> = DynamicDefaultRawDataFields> = {
|
|
21
|
+
// 不可變更的基本欄位
|
|
22
|
+
id?: string
|
|
23
|
+
name?: string
|
|
24
|
+
source?: string
|
|
25
|
+
target?: string
|
|
26
|
+
parent?: string
|
|
27
|
+
data?: any
|
|
28
|
+
} & DynamicFields // 可變更的欄位
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
// export type DynamicRawDataColumn<
|
|
33
|
+
// ValueField extends string = 'value',
|
|
34
|
+
// DatasetField extends string = 'dataset',
|
|
35
|
+
// SeriesField extends string = 'series',
|
|
36
|
+
// CategoryField extends string = 'category'
|
|
37
|
+
// > = {
|
|
38
|
+
// id?: string
|
|
39
|
+
// name?: string
|
|
40
|
+
// source?: string
|
|
41
|
+
// target?: string
|
|
42
|
+
// parent?: string
|
|
43
|
+
// data?: any
|
|
44
|
+
// } & {
|
|
45
|
+
// [K in ValueField]: number | null
|
|
46
|
+
// } & {
|
|
47
|
+
// [K in DatasetField]?: string
|
|
48
|
+
// } & {
|
|
49
|
+
// [K in SeriesField]?: string
|
|
50
|
+
// } & {
|
|
51
|
+
// [K in CategoryField]?: string
|
|
52
|
+
// }
|
|
53
|
+
|
|
54
|
+
// export type FlexibleRawDataColumn<T extends Record<string, any> = {}> = {
|
|
55
|
+
// id?: string
|
|
56
|
+
// value?: number | null
|
|
57
|
+
// name?: string
|
|
58
|
+
// dataset?: string
|
|
59
|
+
// series?: string
|
|
60
|
+
// category?: string
|
|
61
|
+
// source?: string
|
|
62
|
+
// target?: string
|
|
63
|
+
// parent?: string
|
|
64
|
+
// data?: any
|
|
65
|
+
// } & T
|
|
66
|
+
|
|
67
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ModelType,
|
|
3
|
+
ModelDatum,
|
|
4
|
+
ModelDatumGraphEdge
|
|
5
|
+
} from './index'
|
|
6
|
+
|
|
7
|
+
// 基礎型別,其他欄位留給 Plugin 擴充
|
|
8
|
+
// export interface RenderDatumBase<T extends ModelType> {
|
|
9
|
+
// modelDatum: ModelDatum<T>
|
|
10
|
+
// }
|
|
11
|
+
export type RenderDatumBase<
|
|
12
|
+
T extends ModelType,
|
|
13
|
+
ExtendTypes extends Record<string, any> = {}
|
|
14
|
+
> = ModelDatum<T> & ExtendTypes
|
|
15
|
+
|
|
16
|
+
export type RenderDatumGraphEdge<ExtendTypes extends Record<string, any> = {}> = ModelDatumGraphEdge & ExtendTypes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
export interface Colors {
|
|
3
|
+
data: string[],
|
|
4
|
+
primary: string,
|
|
5
|
+
secondary: string,
|
|
6
|
+
dataContrast: string[],
|
|
7
|
+
background: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ColorScheme = 'light' | 'dark'
|
|
11
|
+
|
|
12
|
+
export interface Theme {
|
|
13
|
+
colorScheme: ColorScheme | 'auto'
|
|
14
|
+
colors: {
|
|
15
|
+
light: Colors,
|
|
16
|
+
dark: Colors
|
|
17
|
+
},
|
|
18
|
+
fontSize: string | number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ColorType = 'none' | keyof Colors
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type ToBeTypes = 'string' | 'number' | 'boolean' | 'object' | 'object[]' | 'string[]' | 'number[]' | 'Function' | 'null' | 'undefined'
|
|
2
|
+
|
|
3
|
+
export type ToBeOption = 'ColorType'
|
|
4
|
+
|
|
5
|
+
// 有使用定義好的型別則不需寫 validate
|
|
6
|
+
export interface ValidatorRuleToBeTypes {
|
|
7
|
+
toBeTypes: ToBeTypes[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// 自訂規則
|
|
11
|
+
export interface ValidatorRuleToBe {
|
|
12
|
+
toBe: string
|
|
13
|
+
test: (value: any) => boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 選項資料型別
|
|
17
|
+
export interface ValidatorRuleToBeOption {
|
|
18
|
+
toBeOption: ToBeOption
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ValidatorRule<T> = {[key in keyof T]: ValidatorRuleToBeTypes | ValidatorRuleToBe | ValidatorRuleToBeOption}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// export type ValidateObject<T> = (data: T, rules: ValidatorRule<T>) => ValidatorResult
|
|
25
|
+
|
|
26
|
+
// export interface ValidatorUtils {
|
|
27
|
+
// validateObject: typeof validateObject // 我發現要這樣寫才能夠透過 data 型別自動推斷出 T,不曉得有沒有更好的寫法
|
|
28
|
+
// }
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export interface ValidatorResult {
|
|
32
|
+
status: 'success' | 'warning' | 'error'
|
|
33
|
+
// message: string // warning or error message
|
|
34
|
+
columnName: string,
|
|
35
|
+
expectToBe: string,
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './Chart'
|
|
2
|
+
export * from './ChartContext'
|
|
3
|
+
export * from './Encoding'
|
|
4
|
+
export * from './Event'
|
|
5
|
+
export * from './Layers'
|
|
6
|
+
export * from './ModelData'
|
|
7
|
+
export * from './Plugin'
|
|
8
|
+
export * from './RawData'
|
|
9
|
+
export * from './RenderData'
|
|
10
|
+
export * from './Theme'
|
|
11
|
+
export * from './Validator'
|
|
12
|
+
export * from './Common'
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 聚合函數工具集
|
|
3
|
+
* 用於處理數值陣列的各種聚合運算
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type AggregateType = 'sum' | 'mean' | 'median' | 'min' | 'max' | 'count' | 'none'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 計算數值陣列的總和
|
|
10
|
+
*/
|
|
11
|
+
export function sum(values: (number | null)[]): number | null {
|
|
12
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
13
|
+
if (validValues.length === 0) return null
|
|
14
|
+
return validValues.reduce((acc, val) => acc + val, 0)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 計算數值陣列的平均值
|
|
19
|
+
*/
|
|
20
|
+
export function mean(values: (number | null)[]): number | null {
|
|
21
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
22
|
+
if (validValues.length === 0) return null
|
|
23
|
+
const total = validValues.reduce((acc, val) => acc + val, 0)
|
|
24
|
+
return total / validValues.length
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 計算數值陣列的中位數
|
|
29
|
+
*/
|
|
30
|
+
export function median(values: (number | null)[]): number | null {
|
|
31
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
32
|
+
if (validValues.length === 0) return null
|
|
33
|
+
|
|
34
|
+
const sorted = [...validValues].sort((a, b) => a - b)
|
|
35
|
+
const mid = Math.floor(sorted.length / 2)
|
|
36
|
+
|
|
37
|
+
if (sorted.length % 2 === 0) {
|
|
38
|
+
return (sorted[mid - 1] + sorted[mid]) / 2
|
|
39
|
+
} else {
|
|
40
|
+
return sorted[mid]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 計算數值陣列的最小值
|
|
46
|
+
*/
|
|
47
|
+
export function min(values: (number | null)[]): number | null {
|
|
48
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
49
|
+
if (validValues.length === 0) return null
|
|
50
|
+
return Math.min(...validValues)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 計算數值陣列的最大值
|
|
55
|
+
*/
|
|
56
|
+
export function max(values: (number | null)[]): number | null {
|
|
57
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
58
|
+
if (validValues.length === 0) return null
|
|
59
|
+
return Math.max(...validValues)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 計算數值陣列的有效數量
|
|
64
|
+
*/
|
|
65
|
+
export function count(values: (number | null)[]): number {
|
|
66
|
+
return values.filter((v): v is number => v !== null && !isNaN(v)).length
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 不進行聚合,返回第一個有效值
|
|
71
|
+
*/
|
|
72
|
+
export function none(values: (number | null)[]): number | null {
|
|
73
|
+
const validValues = values.filter((v): v is number => v !== null && !isNaN(v))
|
|
74
|
+
return validValues.length > 0 ? validValues[0] : null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 根據聚合類型執行對應的聚合函數
|
|
79
|
+
*/
|
|
80
|
+
export function aggregate(values: (number | null)[], type: AggregateType): number | null {
|
|
81
|
+
switch (type) {
|
|
82
|
+
case 'sum':
|
|
83
|
+
return sum(values)
|
|
84
|
+
case 'mean':
|
|
85
|
+
return mean(values)
|
|
86
|
+
case 'median':
|
|
87
|
+
return median(values)
|
|
88
|
+
case 'min':
|
|
89
|
+
return min(values)
|
|
90
|
+
case 'max':
|
|
91
|
+
return max(values)
|
|
92
|
+
case 'count':
|
|
93
|
+
return count(values)
|
|
94
|
+
case 'none':
|
|
95
|
+
return none(values)
|
|
96
|
+
default:
|
|
97
|
+
throw new Error(`Unknown aggregate type: ${type}`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Theme } from '../types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 根據索引和主題計算對應的顏色
|
|
5
|
+
* @param index 索引值
|
|
6
|
+
* @param theme 主題設定
|
|
7
|
+
* @returns 對應的顏色(hex 格式)
|
|
8
|
+
*/
|
|
9
|
+
export function getColorByIndex(index: number, theme: Theme): string {
|
|
10
|
+
// 根據 colorScheme 決定使用哪個色彩方案
|
|
11
|
+
let colorScheme: 'light' | 'dark'
|
|
12
|
+
if (theme.colorScheme === 'auto') {
|
|
13
|
+
// 可以根據系統設定或其他邏輯來決定,這裡預設使用 light
|
|
14
|
+
colorScheme = 'light'
|
|
15
|
+
} else {
|
|
16
|
+
colorScheme = theme.colorScheme
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const dataColors = theme.colors[colorScheme].data
|
|
20
|
+
|
|
21
|
+
// 使用模運算來循環使用色票
|
|
22
|
+
const colorIndex = index % dataColors.length
|
|
23
|
+
return dataColors[colorIndex]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 根據不同的 encoding.color.from 計算顏色
|
|
28
|
+
* @param colorFrom 顏色來源類型
|
|
29
|
+
* @param options 包含所有可能索引的選項物件
|
|
30
|
+
* @param theme 主題設定
|
|
31
|
+
* @returns 對應的顏色(hex 格式)
|
|
32
|
+
*/
|
|
33
|
+
export function getColorByFrom(
|
|
34
|
+
colorFrom: 'index' | 'series' | 'category' | 'dataset',
|
|
35
|
+
options: {
|
|
36
|
+
index?: number
|
|
37
|
+
seriesIndex?: number
|
|
38
|
+
categoryIndex?: number
|
|
39
|
+
datasetIndex?: number
|
|
40
|
+
},
|
|
41
|
+
theme: Theme
|
|
42
|
+
): string {
|
|
43
|
+
let targetIndex: number
|
|
44
|
+
|
|
45
|
+
switch (colorFrom) {
|
|
46
|
+
case 'index':
|
|
47
|
+
targetIndex = options.index ?? 0
|
|
48
|
+
break
|
|
49
|
+
case 'series':
|
|
50
|
+
targetIndex = options.seriesIndex ?? 0
|
|
51
|
+
break
|
|
52
|
+
case 'category':
|
|
53
|
+
targetIndex = options.categoryIndex ?? 0
|
|
54
|
+
break
|
|
55
|
+
case 'dataset':
|
|
56
|
+
targetIndex = options.datasetIndex ?? 0
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
targetIndex = 0
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return getColorByIndex(targetIndex, theme)
|
|
63
|
+
}
|
package/src/utils/commonUtils.ts
CHANGED
|
@@ -1,55 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
parts
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
1
|
+
import { DeepPartial } from "../types/Common";
|
|
2
|
+
|
|
3
|
+
// 是否為原始物件
|
|
4
|
+
export function isPlainObject(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
|
+
return Object.prototype.toString.call(fn) === '[object Function]'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 是否為dom
|
|
15
|
+
export function isDom(obj: any) {
|
|
16
|
+
return !!(obj && obj.nodeType);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 將可選的參數和預設值合併
|
|
20
|
+
export function deepOverwrite<DeepRecord extends Record<string, any>>(full: DeepRecord, options: DeepPartial<DeepRecord>): DeepRecord {
|
|
21
|
+
if (isPlainObject(options) === false || isPlainObject(full) === false) {
|
|
22
|
+
return Object.assign({}, full)
|
|
23
|
+
}
|
|
24
|
+
const mergeObject = (_full: DeepRecord, _options: DeepPartial<DeepRecord>) => {
|
|
25
|
+
const obj: DeepRecord = (Object.assign({}, _full) as any)
|
|
26
|
+
for (let key of Object.keys(_options)) {
|
|
27
|
+
if ((key in _full) == false) {
|
|
28
|
+
continue
|
|
29
|
+
}
|
|
30
|
+
let objValue: any = undefined
|
|
31
|
+
// 下一層的plain object
|
|
32
|
+
if (isPlainObject(_options[key]) && isPlainObject(_full[key])) {
|
|
33
|
+
objValue = mergeObject(_full[key], _options[key])
|
|
34
|
+
obj[key as keyof DeepRecord] = objValue
|
|
35
|
+
}
|
|
36
|
+
// 不是plain object直接賦值
|
|
37
|
+
else {
|
|
38
|
+
obj[key as keyof DeepRecord] = _options[key] as DeepRecord[typeof key]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return obj
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return mergeObject(full, options)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 加上千分位 ,
|
|
48
|
+
export function formatCommaNumber (num = 0): string {
|
|
49
|
+
try {
|
|
50
|
+
let parts = num.toString().split('.');
|
|
51
|
+
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
52
|
+
return parts.join('.');
|
|
53
|
+
} catch (e: any) {
|
|
54
|
+
console.error(e)
|
|
55
|
+
}
|
|
56
|
+
}
|