@orbcharts/core 3.0.7 → 4.0.0-pre-alpha.1
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/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 +26 -13
- 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 +6 -18
- 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 +12 -11
- package/src/utils/dom-lifecycle.ts +164 -0
- package/src/utils/dom.ts +55 -0
- package/src/utils/index.ts +6 -2
- package/src/utils/observables.ts +1 -292
- package/src/utils/orbchartsUtils.ts +6 -393
- package/src/utils/validator.ts +15 -14
- 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,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Subject,
|
|
3
|
+
BehaviorSubject,
|
|
4
|
+
filter,
|
|
5
|
+
takeUntil,
|
|
6
|
+
switchMap,
|
|
7
|
+
combineLatest,
|
|
8
|
+
of,
|
|
9
|
+
map,
|
|
10
|
+
shareReplay,
|
|
11
|
+
debounceTime,
|
|
12
|
+
} from "rxjs"
|
|
13
|
+
import type {
|
|
14
|
+
DefineLayerConfig,
|
|
15
|
+
LayerEntity,
|
|
16
|
+
ExtendableContext,
|
|
17
|
+
LayerEnableProps
|
|
18
|
+
} from "../types"
|
|
19
|
+
import { deepOverwrite } from "../utils/commonUtils"
|
|
20
|
+
import { createOrbChartsErrorMessage, createValidatorErrorMessage, createValidatorWarningMessage } from "../utils"
|
|
21
|
+
|
|
22
|
+
export const createLayer = <
|
|
23
|
+
ExtendContext extends ExtendableContext,
|
|
24
|
+
PluginParams extends Record<string, any>,
|
|
25
|
+
LayerParams extends Record<string, any>
|
|
26
|
+
>(elementType: 'canvas' | 'svg', config: DefineLayerConfig<'svg' | 'canvas', ExtendContext, PluginParams, LayerParams>): LayerEntity<ExtendContext, PluginParams, LayerParams> => {
|
|
27
|
+
|
|
28
|
+
// let svgElement: SVGSVGElement | null = null
|
|
29
|
+
// let canvasElement: HTMLCanvasElement | null = null
|
|
30
|
+
|
|
31
|
+
const layerParams$ = new BehaviorSubject<LayerParams>(Object.assign({}, config.defaultParams))
|
|
32
|
+
|
|
33
|
+
// let _context: ChartContext<ExtendContext> = {} as ChartContext<ExtendContext>
|
|
34
|
+
let destroySetup = () => {}
|
|
35
|
+
|
|
36
|
+
const enableProps$ = new BehaviorSubject<LayerEnableProps<'svg' | 'canvas', ExtendContext, PluginParams, LayerParams> | null>(null)
|
|
37
|
+
|
|
38
|
+
const enabledProps$ = enableProps$.pipe(
|
|
39
|
+
filter(enableProps => enableProps !== null)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
// show
|
|
43
|
+
combineLatest({
|
|
44
|
+
layerParams: layerParams$,
|
|
45
|
+
enabledProps: enabledProps$
|
|
46
|
+
}).pipe(
|
|
47
|
+
debounceTime(0)
|
|
48
|
+
).subscribe(({ layerParams, enabledProps }) => {
|
|
49
|
+
destroySetup()
|
|
50
|
+
destroySetup = elementType === 'svg' ?
|
|
51
|
+
config.setup({
|
|
52
|
+
svgG: (enabledProps as LayerEnableProps<'svg', ExtendContext, PluginParams, LayerParams>).svgG,
|
|
53
|
+
// canvas: enabledProps.canvas,
|
|
54
|
+
// context: Object.assign({}, enabledProps.context),
|
|
55
|
+
context: enabledProps.context,
|
|
56
|
+
pluginParams$: enabledProps.pluginParams$,
|
|
57
|
+
layerParams$: layerParams$.pipe(
|
|
58
|
+
map(params => {
|
|
59
|
+
return deepOverwrite(params, enabledProps.initLayerParams ?? {})
|
|
60
|
+
}),
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
: config.setup({
|
|
64
|
+
// svgG: enabledProps.svgG,
|
|
65
|
+
canvas: (enabledProps as LayerEnableProps<'canvas', ExtendContext, PluginParams, LayerParams>).canvas,
|
|
66
|
+
// context: Object.assign({}, enabledProps.context),
|
|
67
|
+
context: enabledProps.context,
|
|
68
|
+
pluginParams$: enabledProps.pluginParams$,
|
|
69
|
+
layerParams$: layerParams$.pipe(
|
|
70
|
+
map(params => {
|
|
71
|
+
return deepOverwrite(params, enabledProps.initLayerParams ?? {})
|
|
72
|
+
}),
|
|
73
|
+
)
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
// hide
|
|
78
|
+
enableProps$.pipe(filter(enableProps => enableProps === null)).subscribe(() => {
|
|
79
|
+
destroySetup()
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
_name: config.name,
|
|
84
|
+
_defaultParams: config.defaultParams,
|
|
85
|
+
_layerIndex: config.layerIndex,
|
|
86
|
+
_initShow: config.initShow,
|
|
87
|
+
_enable: (enableProps) => {
|
|
88
|
+
enableProps$.next(enableProps)
|
|
89
|
+
},
|
|
90
|
+
_disable: () => {
|
|
91
|
+
enableProps$.next(null)
|
|
92
|
+
},
|
|
93
|
+
// setParams: (partial) => {
|
|
94
|
+
// previousParams$.next(deepOverwrite(defaultParams$.getValue(), partial))
|
|
95
|
+
// },
|
|
96
|
+
_updateParams: (patch) => {
|
|
97
|
+
try {
|
|
98
|
+
// 檢查 data$ 資料格式是否正確
|
|
99
|
+
const { status, columnName, expectToBe } = config.validator(patch)
|
|
100
|
+
if (status === 'error') {
|
|
101
|
+
throw new Error(createValidatorErrorMessage({
|
|
102
|
+
columnName,
|
|
103
|
+
expectToBe,
|
|
104
|
+
from: `${config.name}.params$`
|
|
105
|
+
}))
|
|
106
|
+
} else if (status === 'warning') {
|
|
107
|
+
console.warn(createValidatorWarningMessage({
|
|
108
|
+
columnName,
|
|
109
|
+
expectToBe,
|
|
110
|
+
from: `${config.name}.params$`
|
|
111
|
+
}))
|
|
112
|
+
}
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// throw new Error(e.message)
|
|
115
|
+
// 驗證失敗仍繼續執行,才不會把 Observable 資料流給中斷掉
|
|
116
|
+
console.error(createOrbChartsErrorMessage(e))
|
|
117
|
+
}
|
|
118
|
+
const layerParams = deepOverwrite(layerParams$.getValue(), patch)
|
|
119
|
+
layerParams$.next(layerParams)
|
|
120
|
+
},
|
|
121
|
+
_forceReplaceParams: (full) => {
|
|
122
|
+
layerParams$.next(full)
|
|
123
|
+
},
|
|
124
|
+
_getParams: () => {
|
|
125
|
+
return layerParams$.getValue()
|
|
126
|
+
},
|
|
127
|
+
// injectContext: (context) => {
|
|
128
|
+
// _context = Object.assign({}, context)
|
|
129
|
+
// // re-setup layer with new context
|
|
130
|
+
// enableProps$.next(true)
|
|
131
|
+
// },
|
|
132
|
+
_destroy: () => {
|
|
133
|
+
enableProps$.next(null)
|
|
134
|
+
enableProps$.complete()
|
|
135
|
+
layerParams$.complete()
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import type { ChartContext, DeepPartial, DefinePluginConfig, ExtendableContext, PluginEntity } from '../types'
|
|
2
|
+
import {
|
|
3
|
+
BehaviorSubject,
|
|
4
|
+
combineLatest,
|
|
5
|
+
switchMap,
|
|
6
|
+
map,
|
|
7
|
+
filter,
|
|
8
|
+
of,
|
|
9
|
+
shareReplay,
|
|
10
|
+
debounceTime,
|
|
11
|
+
first,
|
|
12
|
+
Observable,
|
|
13
|
+
Subject,
|
|
14
|
+
} from 'rxjs'
|
|
15
|
+
import type { PluginSetupProps, LayerEnableProps } from '../types'
|
|
16
|
+
// import { handleElementLifecycle } from '../utils/dom-lifecycle'
|
|
17
|
+
// import { createSVG, createCanvasElement, createSVGGroup, createCanvas } from '../utils/dom'
|
|
18
|
+
// import { createPluginClassName, createLayerClassName } from '../utils/orbchartsUtils'
|
|
19
|
+
import { deepOverwrite } from '../utils/commonUtils'
|
|
20
|
+
import { createOrbChartsErrorMessage, createValidatorErrorMessage, createValidatorWarningMessage } from '../utils/errorMessage'
|
|
21
|
+
|
|
22
|
+
export const createPlugin = <
|
|
23
|
+
ElementType extends 'svg' | 'canvas',
|
|
24
|
+
ExtendContext extends ExtendableContext,
|
|
25
|
+
PluginParams,
|
|
26
|
+
AllLayerParams
|
|
27
|
+
>(elementType: ElementType, config: DefinePluginConfig<ExtendContext, PluginParams, AllLayerParams>, initPluginParams?: DeepPartial<PluginParams | AllLayerParams>): PluginEntity<ElementType, PluginParams, AllLayerParams> => {
|
|
28
|
+
// const svgClassName = `${createPluginClassName(config.name)}__svg`
|
|
29
|
+
// const svgGClassName = `${createPluginClassName(config.name)}__g`
|
|
30
|
+
// const canvasClassName = `${createPluginClassName(config.name)}__canvas`
|
|
31
|
+
|
|
32
|
+
// 內部保存起來的 id
|
|
33
|
+
let _id = config.name
|
|
34
|
+
|
|
35
|
+
let destroySetup = () => {}
|
|
36
|
+
|
|
37
|
+
const context$ = new BehaviorSubject<ChartContext<ExtendContext> | null>(null)
|
|
38
|
+
const injectedContext$ = context$.pipe(
|
|
39
|
+
filter((context): context is ChartContext<ExtendContext> => context !== null)
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
// element 全部保存起來避免重複創建
|
|
43
|
+
// const layerSVGElementsRef: Record<string, SVGElement> = {}
|
|
44
|
+
// const layerCanvasElementsRef: Record<string, HTMLCanvasElement> = {}
|
|
45
|
+
|
|
46
|
+
// 全部的layers
|
|
47
|
+
const allLayerInstances = {
|
|
48
|
+
// 將陣列轉成字典
|
|
49
|
+
...config.layers.reduce((acc, layer) => {
|
|
50
|
+
acc[layer._name as keyof AllLayerParams] = layer
|
|
51
|
+
return acc
|
|
52
|
+
}, {} as Record<keyof AllLayerParams, typeof config.layers[number]>)
|
|
53
|
+
}
|
|
54
|
+
const getAllLayerNamesSet = () => new Set(config.layers.map(l => l._name as keyof AllLayerParams))
|
|
55
|
+
// const getParamsKeySet = (params: DeepPartial<PluginParams | AllLayerParams>): Set<keyof AllLayerParams> => {
|
|
56
|
+
// // 取得有設定 params 的 layer name
|
|
57
|
+
// if (params) {
|
|
58
|
+
// const AllLayerNamesSet = getAllLayerNamesSet()
|
|
59
|
+
// const keysOfParams = Object.keys(params) as (keyof AllLayerParams)[]
|
|
60
|
+
// return new Set(keysOfParams.filter(key => AllLayerNamesSet.has(key)))
|
|
61
|
+
// }
|
|
62
|
+
// return new Set()
|
|
63
|
+
// }
|
|
64
|
+
const getParamsKeys = (params: DeepPartial<PluginParams | AllLayerParams>): (keyof AllLayerParams)[] => {
|
|
65
|
+
// 取得有設定 params 的 layer name
|
|
66
|
+
if (params) {
|
|
67
|
+
const AllLayerNamesSet = getAllLayerNamesSet()
|
|
68
|
+
const keysOfParams = Object.keys(params) as (keyof AllLayerParams)[]
|
|
69
|
+
return keysOfParams.filter(key => AllLayerNamesSet.has(key))
|
|
70
|
+
}
|
|
71
|
+
return []
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// config 設定顯示的 layers
|
|
75
|
+
const systemInitLayerNames = config.layers.reduce((prev, current) => {
|
|
76
|
+
if (current._initShow) {
|
|
77
|
+
prev.push(current._name as keyof AllLayerParams)
|
|
78
|
+
}
|
|
79
|
+
return prev
|
|
80
|
+
}, [] as (keyof AllLayerParams)[])
|
|
81
|
+
// 有設定 params 對應的 layers 名稱
|
|
82
|
+
const initLayerNames = getParamsKeys(initPluginParams)
|
|
83
|
+
// const InitLayerNameSet$ = new BehaviorSubject<Set<keyof AllLayerParams>>(getParamsKeySet(initPluginParams))
|
|
84
|
+
// 有設定 show/showOnly 等的 layers 名稱
|
|
85
|
+
const ShownLayerNameSet$ = new BehaviorSubject<Set<keyof AllLayerParams>>(
|
|
86
|
+
new Set(initLayerNames.length > 0 ? initLayerNames : systemInitLayerNames)
|
|
87
|
+
)
|
|
88
|
+
// 顯示的 layers 名稱
|
|
89
|
+
// const getShownLayerNames = ({ InitLayerNameSet, IsShowLayerNameSet }: { InitLayerNameSet: Set<keyof AllLayerParams>, IsShowLayerNameSet: Set<keyof AllLayerParams> | null }) => {
|
|
90
|
+
// const ShownLayerNameSet = IsShowLayerNameSet == null ? InitLayerNameSet : IsShowLayerNameSet // IsShowLayerNameSet 預設為 null
|
|
91
|
+
// return ShownLayerNameSet
|
|
92
|
+
// }
|
|
93
|
+
// const ShownLayerNameSet$ = combineLatest({
|
|
94
|
+
// InitLayerNameSet: InitLayerNameSet$,
|
|
95
|
+
// IsShowLayerNameSet: IsShowLayerNameSet$
|
|
96
|
+
// }).pipe(
|
|
97
|
+
// debounceTime(0),
|
|
98
|
+
// // filter(({ context }) => context !== null),
|
|
99
|
+
// map(({ InitLayerNameSet, IsShowLayerNameSet }) => {
|
|
100
|
+
// return getShownLayerNames({ InitLayerNameSet, IsShowLayerNameSet })
|
|
101
|
+
// })
|
|
102
|
+
// )
|
|
103
|
+
// 顯示的 layers 名稱依照 layerIndex 排序
|
|
104
|
+
const shownLayerNamesSeq$ = ShownLayerNameSet$.pipe(
|
|
105
|
+
map(ShownLayerNameSet => {
|
|
106
|
+
// 依照 layerIndex 排序
|
|
107
|
+
const shownLayerNamesSeq: string[] = Array.from(ShownLayerNameSet)
|
|
108
|
+
.map(name => [
|
|
109
|
+
name,
|
|
110
|
+
config.layers.find(l => l._name === name)?._layerIndex ?? -1
|
|
111
|
+
])
|
|
112
|
+
.filter(([, index]) => index !== -1)
|
|
113
|
+
.sort((a, b) => (a[1] as number) - (b[1] as number))
|
|
114
|
+
.map(([name]) => name as string)
|
|
115
|
+
return shownLayerNamesSeq
|
|
116
|
+
})
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
// plugin 的根元素
|
|
120
|
+
// const pluginElement$: Observable<SVGGElement | HTMLCanvasElement> = injectedContext$.pipe(
|
|
121
|
+
// map(context => {
|
|
122
|
+
// // -- 在 svg 或 canvas 元素底下建立 plugin 的元素 --
|
|
123
|
+
// if (elementType === 'svg') {
|
|
124
|
+
// let svgGElement: SVGGElement | null = context.svg.querySelector(`.${svgGClassName}`)
|
|
125
|
+
// if (!svgGElement) {
|
|
126
|
+
// svgGElement = createSVGGroup(svgGClassName)
|
|
127
|
+
// context.svg.appendChild(svgGElement)
|
|
128
|
+
// }
|
|
129
|
+
// return svgGElement
|
|
130
|
+
// } else if (elementType === 'canvas') {
|
|
131
|
+
// let canvasElement: HTMLCanvasElement | null = context.canvas.querySelector(`.${canvasClassName}`)
|
|
132
|
+
// if (!canvasElement) {
|
|
133
|
+
// canvasElement = createCanvasElement(canvasClassName)
|
|
134
|
+
// context.canvas.appendChild(canvasElement)
|
|
135
|
+
// }
|
|
136
|
+
// return canvasElement
|
|
137
|
+
// }
|
|
138
|
+
// })
|
|
139
|
+
// )
|
|
140
|
+
|
|
141
|
+
// update plugin params
|
|
142
|
+
const patchPluginParams$ = new BehaviorSubject<DeepPartial<AllLayerParams | PluginParams> | undefined>(
|
|
143
|
+
initPluginParams ?? {}
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
// force replace plugin params
|
|
147
|
+
const forceReplacePluginParams$ = new Subject<DeepPartial<AllLayerParams | PluginParams> | undefined>()
|
|
148
|
+
|
|
149
|
+
const pluginParams$ = new Observable<PluginParams>(subscriber => {
|
|
150
|
+
// -- update --
|
|
151
|
+
patchPluginParams$.subscribe(patch => {
|
|
152
|
+
try {
|
|
153
|
+
// 檢查 data$ 資料格式是否正確
|
|
154
|
+
const { status, columnName, expectToBe } = config.validator(patch)
|
|
155
|
+
if (status === 'error') {
|
|
156
|
+
throw new Error(createValidatorErrorMessage({
|
|
157
|
+
columnName,
|
|
158
|
+
expectToBe,
|
|
159
|
+
from: `${config.name}.params$`
|
|
160
|
+
}))
|
|
161
|
+
} else if (status === 'warning') {
|
|
162
|
+
console.warn(createValidatorWarningMessage({
|
|
163
|
+
columnName,
|
|
164
|
+
expectToBe,
|
|
165
|
+
from: `${config.name}.params$`
|
|
166
|
+
}))
|
|
167
|
+
}
|
|
168
|
+
} catch (e) {
|
|
169
|
+
// throw new Error(e.message)
|
|
170
|
+
// 驗證失敗仍繼續執行,才不會把 Observable 資料流給中斷掉
|
|
171
|
+
console.error(createOrbChartsErrorMessage(e))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const newParams = deepOverwrite(config.defaultParams, patch as DeepPartial<PluginParams> ?? {})
|
|
175
|
+
// console.log('newParams', newParams)
|
|
176
|
+
subscriber.next(newParams)
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// -- force replace --
|
|
180
|
+
forceReplacePluginParams$.subscribe(full => {
|
|
181
|
+
subscriber.next(full as PluginParams)
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// patchPluginParams$.pipe(
|
|
186
|
+
// map(patch => {
|
|
187
|
+
// try {
|
|
188
|
+
// // 檢查 data$ 資料格式是否正確
|
|
189
|
+
// const { status, columnName, expectToBe } = config.validator(patch)
|
|
190
|
+
// if (status === 'error') {
|
|
191
|
+
// throw new Error(createValidatorErrorMessage({
|
|
192
|
+
// columnName,
|
|
193
|
+
// expectToBe,
|
|
194
|
+
// from: `${config.name}.params$`
|
|
195
|
+
// }))
|
|
196
|
+
// } else if (status === 'warning') {
|
|
197
|
+
// console.warn(createValidatorWarningMessage({
|
|
198
|
+
// columnName,
|
|
199
|
+
// expectToBe,
|
|
200
|
+
// from: `${config.name}.params$`
|
|
201
|
+
// }))
|
|
202
|
+
// }
|
|
203
|
+
// } catch (e) {
|
|
204
|
+
// // throw new Error(e.message)
|
|
205
|
+
// // 驗證失敗仍繼續執行,才不會把 Observable 資料流給中斷掉
|
|
206
|
+
// console.error(createOrbChartsErrorMessage(e))
|
|
207
|
+
// }
|
|
208
|
+
|
|
209
|
+
// return deepOverwrite(config.defaultParams, patch as DeepPartial<PluginParams> ?? {})
|
|
210
|
+
// }),
|
|
211
|
+
// shareReplay(1)
|
|
212
|
+
// )
|
|
213
|
+
|
|
214
|
+
const pluginSetupProps$: Observable<PluginSetupProps<ExtendContext, PluginParams>> = injectedContext$.pipe(
|
|
215
|
+
map((context) => {
|
|
216
|
+
// const pluginSetupProps: PluginSetupProps<ExtendContext, PluginParams> =
|
|
217
|
+
// elementType === 'svg' ? {
|
|
218
|
+
// context: context as ChartContext<ExtendContext>, // 初始化時 context 有可能被 in place 擴展
|
|
219
|
+
// svgG: pluginElement as SVGSVGElement,
|
|
220
|
+
// pluginParams$
|
|
221
|
+
// } : {
|
|
222
|
+
// context: context as ChartContext<ExtendContext>,
|
|
223
|
+
// canvas: pluginElement as HTMLCanvasElement,
|
|
224
|
+
// pluginParams$
|
|
225
|
+
// }
|
|
226
|
+
return {
|
|
227
|
+
context, // 初始化時 context 有可能被 in place 擴展
|
|
228
|
+
pluginParams$
|
|
229
|
+
}
|
|
230
|
+
}),
|
|
231
|
+
first() // 只做初始化
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
combineLatest({
|
|
235
|
+
pluginSetupProps: pluginSetupProps$,
|
|
236
|
+
ShownLayerNameSet: ShownLayerNameSet$,
|
|
237
|
+
shownLayerNamesSeq: shownLayerNamesSeq$
|
|
238
|
+
}).pipe(
|
|
239
|
+
debounceTime(0)
|
|
240
|
+
).subscribe(({ pluginSetupProps, ShownLayerNameSet, shownLayerNamesSeq }) => {
|
|
241
|
+
|
|
242
|
+
// 更新 layer elements
|
|
243
|
+
const layerElements = pluginSetupProps.context._updateLayerElements(
|
|
244
|
+
elementType,
|
|
245
|
+
_id,
|
|
246
|
+
shownLayerNamesSeq.map(layer => ({
|
|
247
|
+
pluginId: _id,
|
|
248
|
+
pluginName: config.name,
|
|
249
|
+
layerName: layer,
|
|
250
|
+
layerIndex: allLayerInstances[layer as keyof AllLayerParams]._layerIndex
|
|
251
|
+
}))
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
// init plugin
|
|
255
|
+
if (config.setup) {
|
|
256
|
+
destroySetup = config.setup(pluginSetupProps)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// // layer element - 處理 SVG 元素的 enter/update/exit
|
|
260
|
+
// if (elementType === 'svg') {
|
|
261
|
+
// handleElementLifecycle(
|
|
262
|
+
// // (pluginSetupProps as PluginSetupProps<ExtendContext, PluginParams>).svgG,
|
|
263
|
+
// pluginSetupProps.context.svg,
|
|
264
|
+
// shownLayerNamesSeq, // 依照 shownLayerNamesSeq
|
|
265
|
+
// layerSVGElementsRef,
|
|
266
|
+
// (layerName) => createSVGGroup(createLayerClassName(config.name, layerName))
|
|
267
|
+
// )
|
|
268
|
+
// }
|
|
269
|
+
|
|
270
|
+
// // layer element - 處理 Canvas 元素的 enter/update/exit
|
|
271
|
+
// if (elementType === 'canvas') {
|
|
272
|
+
// handleElementLifecycle(
|
|
273
|
+
// // (pluginSetupProps as PluginSetupProps<ExtendContext, PluginParams>).canvas,
|
|
274
|
+
// pluginSetupProps.context.canvas,
|
|
275
|
+
// shownLayerNamesSeq, // 依照 shownLayerNamesSeq
|
|
276
|
+
// layerCanvasElementsRef,
|
|
277
|
+
// (layerName) => createCanvas(createLayerClassName(config.name, layerName))
|
|
278
|
+
// )
|
|
279
|
+
// }
|
|
280
|
+
|
|
281
|
+
// init layers
|
|
282
|
+
config.layers.forEach((layer) => {
|
|
283
|
+
if (ShownLayerNameSet.has(layer._name as keyof AllLayerParams)) {
|
|
284
|
+
const layerEnableProps: LayerEnableProps<'svg' | 'canvas', ExtendContext, PluginParams, unknown> =
|
|
285
|
+
elementType === 'svg' ?
|
|
286
|
+
{
|
|
287
|
+
// svgG: (pluginSetupProps as PluginSetupProps<'svg', ExtendContext, PluginParams>).svgG.querySelector(`.${createLayerClassName(config.name, layer.name)}`),
|
|
288
|
+
svgG: layerElements[layer._name as keyof AllLayerParams] as SVGGElement,
|
|
289
|
+
// canvas: context.root.querySelector(`.${createLayerClassName(config.name, layer.name)}`),
|
|
290
|
+
// context: Object.assign({}, context) as ChartContext<ExtendContext>,
|
|
291
|
+
context: pluginSetupProps.context,
|
|
292
|
+
pluginParams$,
|
|
293
|
+
initLayerParams: patchPluginParams$.getValue()?.[layer._name as keyof AllLayerParams] as unknown || {}
|
|
294
|
+
}
|
|
295
|
+
: {
|
|
296
|
+
// svgG: context.root.querySelector(`.${createLayerClassName(config.name, layer.name)}`),
|
|
297
|
+
// canvas: (pluginSetupProps as PluginSetupProps<'canvas', ExtendContext, PluginParams>).canvas.querySelector(`.${createLayerClassName(config.name, layer.name)}`),
|
|
298
|
+
canvas: layerElements[layer._name as keyof AllLayerParams] as HTMLCanvasElement,
|
|
299
|
+
// context: Object.assign({}, context) as ChartContext<ExtendContext>,
|
|
300
|
+
context: pluginSetupProps.context,
|
|
301
|
+
pluginParams$,
|
|
302
|
+
initLayerParams: patchPluginParams$.getValue()?.[layer._name as keyof AllLayerParams] as unknown || {}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
layer._enable(layerEnableProps)
|
|
306
|
+
} else {
|
|
307
|
+
layer._disable()
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
// name: `${config.name}-${Math.random().toString(36).substr(2, 9)}`,
|
|
314
|
+
_name: config.name,
|
|
315
|
+
_elementType: elementType,
|
|
316
|
+
// info: {
|
|
317
|
+
// name: config.name,
|
|
318
|
+
// layers: [config.name]
|
|
319
|
+
// } as PluginInfo,
|
|
320
|
+
// layerIndex: config.layerIndex,
|
|
321
|
+
// contextExtension,
|
|
322
|
+
// layer visibility controls
|
|
323
|
+
_getId: () => _id,
|
|
324
|
+
_setId: (id: string) => {
|
|
325
|
+
_id = id
|
|
326
|
+
},
|
|
327
|
+
// 由 chart 注入 context
|
|
328
|
+
_injectContext: (context) => {
|
|
329
|
+
|
|
330
|
+
context$.next(Object.assign({}, context) as ChartContext<ExtendContext>)
|
|
331
|
+
|
|
332
|
+
// context.size$.subscribe(size => {
|
|
333
|
+
// const svgGElement: SVGGElement | null = context.root.querySelector(`.${svgGClassName}`)
|
|
334
|
+
// const canvasElement: HTMLCanvasElement | null = context.root.querySelector(`.${canvasClassName}`)
|
|
335
|
+
// if (svgGElement) {
|
|
336
|
+
// svgGElement.setAttribute('width', size.width.toString())
|
|
337
|
+
// svgGElement.setAttribute('height', size.height.toString())
|
|
338
|
+
// }
|
|
339
|
+
// if (canvasElement) {
|
|
340
|
+
// canvasElement.width = size.width
|
|
341
|
+
// canvasElement.height = size.height
|
|
342
|
+
// }
|
|
343
|
+
// })
|
|
344
|
+
|
|
345
|
+
// if (config.setup) {
|
|
346
|
+
// // const extension: ExtendContext = config.setup(context)
|
|
347
|
+
// // Object.assign(context, extension)
|
|
348
|
+
// config.setup({
|
|
349
|
+
// context: context as ChartContext<ExtendContext>,
|
|
350
|
+
// svg: mainSvgElement!,
|
|
351
|
+
// canvas: mainCanvasElement!,
|
|
352
|
+
// pluginParams$
|
|
353
|
+
// })
|
|
354
|
+
// }
|
|
355
|
+
|
|
356
|
+
// 顯示全部 layers
|
|
357
|
+
// IsShowLayerNameSet$.next(getAllLayerNamesSet())
|
|
358
|
+
},
|
|
359
|
+
show: (names: (keyof AllLayerParams) | (keyof AllLayerParams)[]) => {
|
|
360
|
+
names = Array.isArray(names) ? names : [names]
|
|
361
|
+
ShownLayerNameSet$.next(new Set([...Array.from(ShownLayerNameSet$.getValue()), ...names]))
|
|
362
|
+
},
|
|
363
|
+
showOnly: (names: (keyof AllLayerParams) | (keyof AllLayerParams)[]) => {
|
|
364
|
+
names = Array.isArray(names) ? names : [names]
|
|
365
|
+
ShownLayerNameSet$.next(new Set([...names]))
|
|
366
|
+
},
|
|
367
|
+
showAll: () => {
|
|
368
|
+
ShownLayerNameSet$.next(getAllLayerNamesSet())
|
|
369
|
+
},
|
|
370
|
+
hide: (names: (keyof AllLayerParams) | (keyof AllLayerParams)[]) => {
|
|
371
|
+
names = Array.isArray(names) ? names : [names]
|
|
372
|
+
ShownLayerNameSet$.next(new Set([...Array.from(ShownLayerNameSet$.getValue()).filter(name => !names.includes(name))]))
|
|
373
|
+
},
|
|
374
|
+
hideAll: () => {
|
|
375
|
+
ShownLayerNameSet$.next(new Set())
|
|
376
|
+
},
|
|
377
|
+
toggle: (names: (keyof AllLayerParams) | (keyof AllLayerParams)[]) => {
|
|
378
|
+
names = Array.isArray(names) ? names : [names]
|
|
379
|
+
Array.from(ShownLayerNameSet$.getValue()).forEach(shown => {
|
|
380
|
+
if (names.includes(shown)) {
|
|
381
|
+
names.splice(names.indexOf(shown), 1)
|
|
382
|
+
} else {
|
|
383
|
+
names.push(shown)
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
ShownLayerNameSet$.next(new Set(names))
|
|
387
|
+
},
|
|
388
|
+
getShownLayerNames: () => {
|
|
389
|
+
// const ShownLayerNameSet = getShownLayerNames({
|
|
390
|
+
// InitLayerNameSet: InitLayerNameSet$.getValue(),
|
|
391
|
+
// IsShowLayerNameSet: IsShowLayerNameSet$.getValue()
|
|
392
|
+
// })
|
|
393
|
+
return Array.from(ShownLayerNameSet$.getValue())
|
|
394
|
+
},
|
|
395
|
+
// layer params
|
|
396
|
+
// setLayers: (partial: DeepPartial<PluginParams>) => {
|
|
397
|
+
// params = { ...params, ...partial }
|
|
398
|
+
// },
|
|
399
|
+
updateParams: (patch: DeepPartial<PluginParams | AllLayerParams>) => {
|
|
400
|
+
// plugin params
|
|
401
|
+
patchPluginParams$.next(patch)
|
|
402
|
+
// layer params
|
|
403
|
+
Object.keys(patch).forEach((key) => {
|
|
404
|
+
const layer = allLayerInstances[key as keyof AllLayerParams]
|
|
405
|
+
if (layer) {
|
|
406
|
+
layer._updateParams((patch as Record<string, any>)[key])
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
// InitLayerNameSet$.next(getParamsKeySet(patch))
|
|
411
|
+
},
|
|
412
|
+
forceReplaceParams: (full: PluginParams | AllLayerParams) => {
|
|
413
|
+
// plugin params
|
|
414
|
+
forceReplacePluginParams$.next(full)
|
|
415
|
+
// layer params
|
|
416
|
+
Object.keys(full).forEach((key) => {
|
|
417
|
+
const layer = allLayerInstances[key as keyof AllLayerParams]
|
|
418
|
+
if (layer) {
|
|
419
|
+
layer._forceReplaceParams((full as Record<string, any>)[key])
|
|
420
|
+
}
|
|
421
|
+
})
|
|
422
|
+
// InitLayerNameSet$.next(getParamsKeySet(full))
|
|
423
|
+
},
|
|
424
|
+
getParams: () => {
|
|
425
|
+
return config.layers.reduce((acc, layer) => {
|
|
426
|
+
acc[layer._name] = layer._getParams()
|
|
427
|
+
return acc
|
|
428
|
+
}, {} as Record<string, any>) as PluginParams | AllLayerParams
|
|
429
|
+
},
|
|
430
|
+
// layer: <LayerName extends keyof PluginParams>(name: LayerName) => ({
|
|
431
|
+
// // set: (partial: DeepPartial<PluginParams[LayerName]>) => {
|
|
432
|
+
// // if (params[name]) {
|
|
433
|
+
// // params[name] = { ...params[name], ...partial }
|
|
434
|
+
// // }
|
|
435
|
+
// // },
|
|
436
|
+
// update: (patch: DeepPartial<PluginParams[LayerName]>) => {
|
|
437
|
+
// if (params[name]) {
|
|
438
|
+
// params[name] = { ...params[name], ...patch }
|
|
439
|
+
// }
|
|
440
|
+
// },
|
|
441
|
+
// replace: (full: PluginParams[LayerName]) => {
|
|
442
|
+
// params[name] = full
|
|
443
|
+
// },
|
|
444
|
+
// show: () => {
|
|
445
|
+
// // implementation for showing this layer
|
|
446
|
+
// },
|
|
447
|
+
// hide: () => {
|
|
448
|
+
// // implementation for hiding this layer
|
|
449
|
+
// },
|
|
450
|
+
// toggle: () => {
|
|
451
|
+
// // implementation for toggling this layer
|
|
452
|
+
// }
|
|
453
|
+
// }),
|
|
454
|
+
destroy: () => {
|
|
455
|
+
destroySetup()
|
|
456
|
+
// subscription.unsubscribe()
|
|
457
|
+
context$.complete()
|
|
458
|
+
// IsShowLayerNameSet$.complete()
|
|
459
|
+
ShownLayerNameSet$.complete()
|
|
460
|
+
|
|
461
|
+
config.layers.forEach((layer) => {
|
|
462
|
+
layer._destroy()
|
|
463
|
+
})
|
|
464
|
+
},
|
|
465
|
+
// // outputs
|
|
466
|
+
// layers$: new Observable<Record<string, PluginParams>>(subscriber => {
|
|
467
|
+
// subscriber.next(params)
|
|
468
|
+
// })
|
|
469
|
+
}
|
|
470
|
+
}
|