@orbcharts/core 4.0.0-alpha.0 → 4.0.0-beta.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 +876 -865
- package/dist/orbcharts-core.umd.js +3 -3
- package/dist/src/types/Plugin.d.ts +1 -1
- package/package.json +1 -1
- package/src/OrbCharts.ts +34 -34
- package/src/chart/createChart.ts +1013 -996
- package/src/chart/createGraphData.ts +391 -391
- package/src/chart/createGridData.ts +247 -247
- package/src/chart/createMultivariateData.ts +181 -181
- package/src/chart/createSeriesData.ts +297 -297
- package/src/chart/createTreeData.ts +344 -344
- package/src/chart/defaults.ts +119 -119
- package/src/defineCanvasLayer.ts +23 -23
- package/src/defineCanvasPlugin.ts +38 -38
- package/src/defineSVGLayer.ts +23 -23
- package/src/defineSVGPlugin.ts +38 -38
- package/src/index.ts +8 -8
- package/src/layer/createLayer.ts +137 -137
- package/src/plugin/createPlugin.ts +487 -469
- package/src/test/createGraphData.test.ts +103 -103
- package/src/test/createTreeData.test.ts +97 -97
- package/src/test/simple-graph-test.js +51 -51
- package/src/test/simple-tree-test.js +58 -58
- package/src/types/Chart.ts +62 -62
- package/src/types/ChartContext.ts +41 -41
- package/src/types/Common.ts +4 -4
- package/src/types/Encoding.ts +42 -42
- package/src/types/Event.ts +25 -25
- package/src/types/Layers.ts +92 -92
- package/src/types/ModelData.ts +94 -94
- package/src/types/Plugin.ts +101 -98
- package/src/types/RawData.ts +67 -67
- package/src/types/RenderData.ts +15 -15
- package/src/types/Theme.ts +20 -20
- package/src/types/Validator.ts +35 -35
- package/src/types/index.ts +12 -12
- package/src/utils/aggregateUtils.ts +99 -99
- package/src/utils/colorUtils.ts +63 -63
- package/src/utils/commonUtils.ts +56 -56
- package/src/utils/dom-lifecycle.ts +164 -164
- package/src/utils/dom.ts +54 -54
- package/src/utils/errorMessage.ts +40 -40
- package/src/utils/index.ts +7 -7
- package/src/utils/observables.ts +16 -16
- package/src/utils/orbchartsUtils.ts +8 -8
- package/src/utils/validator.ts +127 -127
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DOM 元素生命週期管理工具
|
|
3
|
-
* 提供類似 D3.js 的 enter/update/exit 模式
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 比較兩個數組是否相等
|
|
8
|
-
*/
|
|
9
|
-
export function arraysEqual<T>(a: T[], b: T[]): boolean {
|
|
10
|
-
if (a.length !== b.length) return false
|
|
11
|
-
return a.every((val, i) => val === b[i])
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 高效的元素重新排序函數,使用最少的 DOM 操作
|
|
16
|
-
*/
|
|
17
|
-
export function reorderElements<T extends Element>(
|
|
18
|
-
parent: Element,
|
|
19
|
-
targetOrder: string[],
|
|
20
|
-
elementsRef: Record<string, T>
|
|
21
|
-
): void {
|
|
22
|
-
// 獲取當前所有相關的子元素
|
|
23
|
-
const currentElements = targetOrder
|
|
24
|
-
.map(name => elementsRef[name])
|
|
25
|
-
.filter(el => el && el.parentNode === parent)
|
|
26
|
-
|
|
27
|
-
if (currentElements.length === 0) return
|
|
28
|
-
|
|
29
|
-
// 檢查當前順序是否已經正確
|
|
30
|
-
let isCorrectOrder = true
|
|
31
|
-
let previousElement: Element | null = null
|
|
32
|
-
|
|
33
|
-
for (const element of currentElements) {
|
|
34
|
-
if (previousElement && previousElement.nextElementSibling !== element) {
|
|
35
|
-
isCorrectOrder = false
|
|
36
|
-
break
|
|
37
|
-
}
|
|
38
|
-
previousElement = element
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 如果順序已經正確,直接返回
|
|
42
|
-
if (isCorrectOrder) return
|
|
43
|
-
|
|
44
|
-
// 使用 DocumentFragment 來批量操作,減少 reflow
|
|
45
|
-
const fragment = document.createDocumentFragment()
|
|
46
|
-
|
|
47
|
-
// 按照目標順序將元素添加到 fragment
|
|
48
|
-
targetOrder.forEach(name => {
|
|
49
|
-
const element = elementsRef[name]
|
|
50
|
-
if (element && element.parentNode === parent) {
|
|
51
|
-
fragment.appendChild(element)
|
|
52
|
-
}
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
// 一次性將所有元素插入回父元素
|
|
56
|
-
parent.appendChild(fragment)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 元素工廠函數類型
|
|
61
|
-
*/
|
|
62
|
-
export type ElementFactory<T extends Element> = (id: string) => T
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* 生命週期鉤子函數類型
|
|
66
|
-
*/
|
|
67
|
-
export interface LifecycleHooks<T extends Element> {
|
|
68
|
-
/** 元素進入時的回調 */
|
|
69
|
-
onEnter?: (element: T, id: string) => void
|
|
70
|
-
/** 元素更新時的回調 */
|
|
71
|
-
onUpdate?: (element: T, id: string) => void
|
|
72
|
-
/** 元素退出前的回調 */
|
|
73
|
-
onExit?: (element: T, id: string) => void
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* D3.js 風格的元素生命週期管理:處理 enter/update/exit
|
|
78
|
-
*
|
|
79
|
-
* @param parent 父容器元素
|
|
80
|
-
* @param targetIds 目標元素 ID 列表(按順序)
|
|
81
|
-
* @param elementsRef 元素引用字典
|
|
82
|
-
* @param createElement 元素創建工廠函數
|
|
83
|
-
* @param hooks 生命週期鉤子函數(可選)
|
|
84
|
-
*/
|
|
85
|
-
export function handleElementLifecycle<T extends Element>(
|
|
86
|
-
parent: Element,
|
|
87
|
-
targetIds: string[],
|
|
88
|
-
elementsRef: Record<string, T>,
|
|
89
|
-
createElement: ElementFactory<T>,
|
|
90
|
-
hooks?: LifecycleHooks<T>
|
|
91
|
-
): void {
|
|
92
|
-
// Exit: 移除不再需要的元素
|
|
93
|
-
const currentIds = Object.keys(elementsRef)
|
|
94
|
-
const toRemove = currentIds.filter(id => !targetIds.includes(id))
|
|
95
|
-
|
|
96
|
-
toRemove.forEach(id => {
|
|
97
|
-
const element = elementsRef[id]
|
|
98
|
-
if (element && element.parentNode === parent) {
|
|
99
|
-
// 執行退出回調
|
|
100
|
-
hooks?.onExit?.(element, id)
|
|
101
|
-
|
|
102
|
-
// 從 DOM 移除
|
|
103
|
-
parent.removeChild(element)
|
|
104
|
-
}
|
|
105
|
-
delete elementsRef[id]
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
// Enter: 創建新元素
|
|
109
|
-
const toAdd = targetIds.filter(id => !elementsRef[id])
|
|
110
|
-
|
|
111
|
-
toAdd.forEach(id => {
|
|
112
|
-
const element = createElement(id)
|
|
113
|
-
elementsRef[id] = element
|
|
114
|
-
parent.appendChild(element)
|
|
115
|
-
|
|
116
|
-
// 執行進入回調
|
|
117
|
-
hooks?.onEnter?.(element, id)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// Update: 處理已存在的元素
|
|
121
|
-
const existing = targetIds.filter(id => elementsRef[id] && !toAdd.includes(id))
|
|
122
|
-
existing.forEach(id => {
|
|
123
|
-
const element = elementsRef[id]
|
|
124
|
-
hooks?.onUpdate?.(element, id)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
// 重新排序所有存在的元素
|
|
128
|
-
if (targetIds.length > 0) {
|
|
129
|
-
reorderElements(parent, targetIds, elementsRef)
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// /**
|
|
134
|
-
// * 創建 SVG group 元素的工廠函數
|
|
135
|
-
// */
|
|
136
|
-
// export function createSVGGroup(className?: string): ElementFactory<SVGGElement> {
|
|
137
|
-
// return (id: string) => {
|
|
138
|
-
// const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
|
|
139
|
-
// g.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
140
|
-
// return g
|
|
141
|
-
// }
|
|
142
|
-
// }
|
|
143
|
-
|
|
144
|
-
// /**
|
|
145
|
-
// * 創建 Canvas 元素的工廠函數
|
|
146
|
-
// */
|
|
147
|
-
// export function createCanvas(className?: string): ElementFactory<HTMLCanvasElement> {
|
|
148
|
-
// return (id: string) => {
|
|
149
|
-
// const canvas = document.createElement('canvas')
|
|
150
|
-
// canvas.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
151
|
-
// return canvas
|
|
152
|
-
// }
|
|
153
|
-
// }
|
|
154
|
-
|
|
155
|
-
// /**
|
|
156
|
-
// * 創建通用 DIV 元素的工廠函數
|
|
157
|
-
// */
|
|
158
|
-
// export function createDiv(className?: string): ElementFactory<HTMLDivElement> {
|
|
159
|
-
// return (id: string) => {
|
|
160
|
-
// const div = document.createElement('div')
|
|
161
|
-
// div.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
162
|
-
// return div
|
|
163
|
-
// }
|
|
164
|
-
// }
|
|
1
|
+
/**
|
|
2
|
+
* DOM 元素生命週期管理工具
|
|
3
|
+
* 提供類似 D3.js 的 enter/update/exit 模式
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 比較兩個數組是否相等
|
|
8
|
+
*/
|
|
9
|
+
export function arraysEqual<T>(a: T[], b: T[]): boolean {
|
|
10
|
+
if (a.length !== b.length) return false
|
|
11
|
+
return a.every((val, i) => val === b[i])
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 高效的元素重新排序函數,使用最少的 DOM 操作
|
|
16
|
+
*/
|
|
17
|
+
export function reorderElements<T extends Element>(
|
|
18
|
+
parent: Element,
|
|
19
|
+
targetOrder: string[],
|
|
20
|
+
elementsRef: Record<string, T>
|
|
21
|
+
): void {
|
|
22
|
+
// 獲取當前所有相關的子元素
|
|
23
|
+
const currentElements = targetOrder
|
|
24
|
+
.map(name => elementsRef[name])
|
|
25
|
+
.filter(el => el && el.parentNode === parent)
|
|
26
|
+
|
|
27
|
+
if (currentElements.length === 0) return
|
|
28
|
+
|
|
29
|
+
// 檢查當前順序是否已經正確
|
|
30
|
+
let isCorrectOrder = true
|
|
31
|
+
let previousElement: Element | null = null
|
|
32
|
+
|
|
33
|
+
for (const element of currentElements) {
|
|
34
|
+
if (previousElement && previousElement.nextElementSibling !== element) {
|
|
35
|
+
isCorrectOrder = false
|
|
36
|
+
break
|
|
37
|
+
}
|
|
38
|
+
previousElement = element
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 如果順序已經正確,直接返回
|
|
42
|
+
if (isCorrectOrder) return
|
|
43
|
+
|
|
44
|
+
// 使用 DocumentFragment 來批量操作,減少 reflow
|
|
45
|
+
const fragment = document.createDocumentFragment()
|
|
46
|
+
|
|
47
|
+
// 按照目標順序將元素添加到 fragment
|
|
48
|
+
targetOrder.forEach(name => {
|
|
49
|
+
const element = elementsRef[name]
|
|
50
|
+
if (element && element.parentNode === parent) {
|
|
51
|
+
fragment.appendChild(element)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// 一次性將所有元素插入回父元素
|
|
56
|
+
parent.appendChild(fragment)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 元素工廠函數類型
|
|
61
|
+
*/
|
|
62
|
+
export type ElementFactory<T extends Element> = (id: string) => T
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 生命週期鉤子函數類型
|
|
66
|
+
*/
|
|
67
|
+
export interface LifecycleHooks<T extends Element> {
|
|
68
|
+
/** 元素進入時的回調 */
|
|
69
|
+
onEnter?: (element: T, id: string) => void
|
|
70
|
+
/** 元素更新時的回調 */
|
|
71
|
+
onUpdate?: (element: T, id: string) => void
|
|
72
|
+
/** 元素退出前的回調 */
|
|
73
|
+
onExit?: (element: T, id: string) => void
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* D3.js 風格的元素生命週期管理:處理 enter/update/exit
|
|
78
|
+
*
|
|
79
|
+
* @param parent 父容器元素
|
|
80
|
+
* @param targetIds 目標元素 ID 列表(按順序)
|
|
81
|
+
* @param elementsRef 元素引用字典
|
|
82
|
+
* @param createElement 元素創建工廠函數
|
|
83
|
+
* @param hooks 生命週期鉤子函數(可選)
|
|
84
|
+
*/
|
|
85
|
+
export function handleElementLifecycle<T extends Element>(
|
|
86
|
+
parent: Element,
|
|
87
|
+
targetIds: string[],
|
|
88
|
+
elementsRef: Record<string, T>,
|
|
89
|
+
createElement: ElementFactory<T>,
|
|
90
|
+
hooks?: LifecycleHooks<T>
|
|
91
|
+
): void {
|
|
92
|
+
// Exit: 移除不再需要的元素
|
|
93
|
+
const currentIds = Object.keys(elementsRef)
|
|
94
|
+
const toRemove = currentIds.filter(id => !targetIds.includes(id))
|
|
95
|
+
|
|
96
|
+
toRemove.forEach(id => {
|
|
97
|
+
const element = elementsRef[id]
|
|
98
|
+
if (element && element.parentNode === parent) {
|
|
99
|
+
// 執行退出回調
|
|
100
|
+
hooks?.onExit?.(element, id)
|
|
101
|
+
|
|
102
|
+
// 從 DOM 移除
|
|
103
|
+
parent.removeChild(element)
|
|
104
|
+
}
|
|
105
|
+
delete elementsRef[id]
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
// Enter: 創建新元素
|
|
109
|
+
const toAdd = targetIds.filter(id => !elementsRef[id])
|
|
110
|
+
|
|
111
|
+
toAdd.forEach(id => {
|
|
112
|
+
const element = createElement(id)
|
|
113
|
+
elementsRef[id] = element
|
|
114
|
+
parent.appendChild(element)
|
|
115
|
+
|
|
116
|
+
// 執行進入回調
|
|
117
|
+
hooks?.onEnter?.(element, id)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
// Update: 處理已存在的元素
|
|
121
|
+
const existing = targetIds.filter(id => elementsRef[id] && !toAdd.includes(id))
|
|
122
|
+
existing.forEach(id => {
|
|
123
|
+
const element = elementsRef[id]
|
|
124
|
+
hooks?.onUpdate?.(element, id)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// 重新排序所有存在的元素
|
|
128
|
+
if (targetIds.length > 0) {
|
|
129
|
+
reorderElements(parent, targetIds, elementsRef)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// /**
|
|
134
|
+
// * 創建 SVG group 元素的工廠函數
|
|
135
|
+
// */
|
|
136
|
+
// export function createSVGGroup(className?: string): ElementFactory<SVGGElement> {
|
|
137
|
+
// return (id: string) => {
|
|
138
|
+
// const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
|
|
139
|
+
// g.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
140
|
+
// return g
|
|
141
|
+
// }
|
|
142
|
+
// }
|
|
143
|
+
|
|
144
|
+
// /**
|
|
145
|
+
// * 創建 Canvas 元素的工廠函數
|
|
146
|
+
// */
|
|
147
|
+
// export function createCanvas(className?: string): ElementFactory<HTMLCanvasElement> {
|
|
148
|
+
// return (id: string) => {
|
|
149
|
+
// const canvas = document.createElement('canvas')
|
|
150
|
+
// canvas.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
151
|
+
// return canvas
|
|
152
|
+
// }
|
|
153
|
+
// }
|
|
154
|
+
|
|
155
|
+
// /**
|
|
156
|
+
// * 創建通用 DIV 元素的工廠函數
|
|
157
|
+
// */
|
|
158
|
+
// export function createDiv(className?: string): ElementFactory<HTMLDivElement> {
|
|
159
|
+
// return (id: string) => {
|
|
160
|
+
// const div = document.createElement('div')
|
|
161
|
+
// div.classList.add(className ? `${className}--${id}` : `layer--${id}`)
|
|
162
|
+
// return div
|
|
163
|
+
// }
|
|
164
|
+
// }
|
package/src/utils/dom.ts
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import { isDom } from "./commonUtils";
|
|
2
|
-
|
|
3
|
-
export function createSVG (className?: string): SVGSVGElement {
|
|
4
|
-
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
5
|
-
svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink')
|
|
6
|
-
svg.setAttribute('xmls', 'http://www.w3.org/2000/svg')
|
|
7
|
-
svg.setAttribute('version', '1.1')
|
|
8
|
-
svg.style.position = 'absolute'
|
|
9
|
-
if (className) {
|
|
10
|
-
svg.classList.add(className)
|
|
11
|
-
}
|
|
12
|
-
return svg
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function createCanvasElement (className?: string): HTMLCanvasElement {
|
|
16
|
-
const canvas = document.createElement('canvas')
|
|
17
|
-
canvas.style.position = 'absolute'
|
|
18
|
-
if (className) {
|
|
19
|
-
canvas.classList.add(className)
|
|
20
|
-
}
|
|
21
|
-
return canvas
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function createSVGGroup(className?: string): SVGGElement {
|
|
25
|
-
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
|
|
26
|
-
if (className) {
|
|
27
|
-
g.classList.add(className)
|
|
28
|
-
}
|
|
29
|
-
return g
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function createCanvas(className?: string): HTMLCanvasElement {
|
|
33
|
-
const canvas = document.createElement('canvas')
|
|
34
|
-
if (className) {
|
|
35
|
-
canvas.classList.add(className)
|
|
36
|
-
}
|
|
37
|
-
return canvas
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function createDiv(className?: string): HTMLDivElement {
|
|
41
|
-
const div = document.createElement('div')
|
|
42
|
-
if (className) {
|
|
43
|
-
div.classList.add(className)
|
|
44
|
-
}
|
|
45
|
-
return div
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 清空 element 底下所有元素
|
|
49
|
-
export function removeElementChildren(el: HTMLElement | Element) {
|
|
50
|
-
if (isDom(el)) {
|
|
51
|
-
while (el.firstChild) {
|
|
52
|
-
el.removeChild(el.firstChild)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
import { isDom } from "./commonUtils";
|
|
2
|
+
|
|
3
|
+
export function createSVG (className?: string): SVGSVGElement {
|
|
4
|
+
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
5
|
+
svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink')
|
|
6
|
+
svg.setAttribute('xmls', 'http://www.w3.org/2000/svg')
|
|
7
|
+
svg.setAttribute('version', '1.1')
|
|
8
|
+
svg.style.position = 'absolute'
|
|
9
|
+
if (className) {
|
|
10
|
+
svg.classList.add(className)
|
|
11
|
+
}
|
|
12
|
+
return svg
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createCanvasElement (className?: string): HTMLCanvasElement {
|
|
16
|
+
const canvas = document.createElement('canvas')
|
|
17
|
+
canvas.style.position = 'absolute'
|
|
18
|
+
if (className) {
|
|
19
|
+
canvas.classList.add(className)
|
|
20
|
+
}
|
|
21
|
+
return canvas
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createSVGGroup(className?: string): SVGGElement {
|
|
25
|
+
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g')
|
|
26
|
+
if (className) {
|
|
27
|
+
g.classList.add(className)
|
|
28
|
+
}
|
|
29
|
+
return g
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function createCanvas(className?: string): HTMLCanvasElement {
|
|
33
|
+
const canvas = document.createElement('canvas')
|
|
34
|
+
if (className) {
|
|
35
|
+
canvas.classList.add(className)
|
|
36
|
+
}
|
|
37
|
+
return canvas
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function createDiv(className?: string): HTMLDivElement {
|
|
41
|
+
const div = document.createElement('div')
|
|
42
|
+
if (className) {
|
|
43
|
+
div.classList.add(className)
|
|
44
|
+
}
|
|
45
|
+
return div
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 清空 element 底下所有元素
|
|
49
|
+
export function removeElementChildren(el: HTMLElement | Element) {
|
|
50
|
+
if (isDom(el)) {
|
|
51
|
+
while (el.firstChild) {
|
|
52
|
+
el.removeChild(el.firstChild)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
55
|
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
// message的prefix - error: 有中斷,warning: 無中斷
|
|
2
|
-
export function createMessagePrefix (status: 'warning' | 'error'): string {
|
|
3
|
-
return `[OrbCharts ${status}]:`
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
// throw到最外層的錯誤訊息
|
|
7
|
-
export function createOrbChartsErrorMessage (e: Error): string {
|
|
8
|
-
return `${createMessagePrefix('error')} ${e.message}`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// 未預期的錯誤
|
|
13
|
-
export function createUnexpectedErrorMessage ({ from, systemMessage }: {
|
|
14
|
-
from: string //
|
|
15
|
-
systemMessage: string // catch 給的的原生錯誤訊息
|
|
16
|
-
}): string {
|
|
17
|
-
return `unexpected error from '${from}':
|
|
18
|
-
${systemMessage}`
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// validator 的 error 訊息
|
|
22
|
-
export function createValidatorErrorMessage ({ columnName, expectToBe, from }: {
|
|
23
|
-
columnName: string // e.g. 'seriesLabels'
|
|
24
|
-
expectToBe: string // e.g. 'string[]'
|
|
25
|
-
from: string // e.g. Chart.chartParams$, Pie.params$
|
|
26
|
-
}): string {
|
|
27
|
-
return `Invalid value: '${columnName}' must be '${expectToBe}'
|
|
28
|
-
|
|
29
|
-
----> find in '${from}'`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// validator 的 warning 訊息
|
|
33
|
-
export function createValidatorWarningMessage ({ columnName, expectToBe, from }: {
|
|
34
|
-
columnName: string // e.g. 'seriesLabels'
|
|
35
|
-
expectToBe: string // e.g. 'string[]'
|
|
36
|
-
from: string // e.g. Chart.chartParams$, Pie.params$
|
|
37
|
-
}): string {
|
|
38
|
-
return `${createMessagePrefix('warning')} Value is not correct: '${columnName}' suppose to be '${expectToBe}', it may cause unexpected errors.'
|
|
39
|
-
|
|
40
|
-
----> find in '${from}'`
|
|
1
|
+
// message的prefix - error: 有中斷,warning: 無中斷
|
|
2
|
+
export function createMessagePrefix (status: 'warning' | 'error'): string {
|
|
3
|
+
return `[OrbCharts ${status}]:`
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// throw到最外層的錯誤訊息
|
|
7
|
+
export function createOrbChartsErrorMessage (e: Error): string {
|
|
8
|
+
return `${createMessagePrefix('error')} ${e.message}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// 未預期的錯誤
|
|
13
|
+
export function createUnexpectedErrorMessage ({ from, systemMessage }: {
|
|
14
|
+
from: string //
|
|
15
|
+
systemMessage: string // catch 給的的原生錯誤訊息
|
|
16
|
+
}): string {
|
|
17
|
+
return `unexpected error from '${from}':
|
|
18
|
+
${systemMessage}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// validator 的 error 訊息
|
|
22
|
+
export function createValidatorErrorMessage ({ columnName, expectToBe, from }: {
|
|
23
|
+
columnName: string // e.g. 'seriesLabels'
|
|
24
|
+
expectToBe: string // e.g. 'string[]'
|
|
25
|
+
from: string // e.g. Chart.chartParams$, Pie.params$
|
|
26
|
+
}): string {
|
|
27
|
+
return `Invalid value: '${columnName}' must be '${expectToBe}'
|
|
28
|
+
|
|
29
|
+
----> find in '${from}'`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// validator 的 warning 訊息
|
|
33
|
+
export function createValidatorWarningMessage ({ columnName, expectToBe, from }: {
|
|
34
|
+
columnName: string // e.g. 'seriesLabels'
|
|
35
|
+
expectToBe: string // e.g. 'string[]'
|
|
36
|
+
from: string // e.g. Chart.chartParams$, Pie.params$
|
|
37
|
+
}): string {
|
|
38
|
+
return `${createMessagePrefix('warning')} Value is not correct: '${columnName}' suppose to be '${expectToBe}', it may cause unexpected errors.'
|
|
39
|
+
|
|
40
|
+
----> find in '${from}'`
|
|
41
41
|
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from './aggregateUtils'
|
|
2
|
-
export * from './colorUtils'
|
|
3
|
-
export * from './commonUtils'
|
|
4
|
-
export * from './dom'
|
|
5
|
-
export * from './errorMessage'
|
|
6
|
-
export * from './observables'
|
|
7
|
-
export * from './orbchartsUtils'
|
|
1
|
+
export * from './aggregateUtils'
|
|
2
|
+
export * from './colorUtils'
|
|
3
|
+
export * from './commonUtils'
|
|
4
|
+
export * from './dom'
|
|
5
|
+
export * from './errorMessage'
|
|
6
|
+
export * from './observables'
|
|
7
|
+
export * from './orbchartsUtils'
|
|
8
8
|
export * from './validator'
|
package/src/utils/observables.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Observable, BehaviorSubject } from 'rxjs'
|
|
2
|
-
|
|
3
|
-
export function resizeObservable(elem: HTMLElement | Element): Observable<DOMRectReadOnly> {
|
|
4
|
-
return new Observable(subscriber => {
|
|
5
|
-
const ro = new ResizeObserver(entries => {
|
|
6
|
-
const entry = entries[0]
|
|
7
|
-
if (entry && entry.contentRect) {
|
|
8
|
-
subscriber.next(entry.contentRect)
|
|
9
|
-
}
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
ro.observe(elem)
|
|
13
|
-
return function unsubscribe() {
|
|
14
|
-
ro.unobserve(elem)
|
|
15
|
-
}
|
|
16
|
-
})
|
|
1
|
+
import { Observable, BehaviorSubject } from 'rxjs'
|
|
2
|
+
|
|
3
|
+
export function resizeObservable(elem: HTMLElement | Element): Observable<DOMRectReadOnly> {
|
|
4
|
+
return new Observable(subscriber => {
|
|
5
|
+
const ro = new ResizeObserver(entries => {
|
|
6
|
+
const entry = entries[0]
|
|
7
|
+
if (entry && entry.contentRect) {
|
|
8
|
+
subscriber.next(entry.contentRect)
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
ro.observe(elem)
|
|
13
|
+
return function unsubscribe() {
|
|
14
|
+
ro.unobserve(elem)
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
17
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
export function createPluginClassName (pluginName: string) {
|
|
3
|
-
return `orbcharts-${pluginName}`
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function createLayerClassName (pluginName: string, layerName: string) {
|
|
7
|
-
// orbcharts-pluginName-layerName
|
|
8
|
-
return `${createPluginClassName(pluginName)}-${layerName}`
|
|
1
|
+
|
|
2
|
+
export function createPluginClassName (pluginName: string) {
|
|
3
|
+
return `orbcharts-${pluginName}`
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function createLayerClassName (pluginName: string, layerName: string) {
|
|
7
|
+
// orbcharts-pluginName-layerName
|
|
8
|
+
return `${createPluginClassName(pluginName)}-${layerName}`
|
|
9
9
|
}
|