@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.
Files changed (198) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +2795 -6591
  3. package/dist/orbcharts-core.umd.js +6 -6
  4. package/dist/src/OrbCharts.d.ts +18 -0
  5. package/dist/src/chart/createChart.d.ts +3 -0
  6. package/dist/src/chart/createGraphData.d.ts +3 -0
  7. package/dist/src/chart/createGridData.d.ts +3 -0
  8. package/dist/src/chart/createMultivariateData.d.ts +3 -0
  9. package/dist/src/chart/createSeriesData.d.ts +3 -0
  10. package/dist/src/chart/createTreeData.d.ts +3 -0
  11. package/dist/src/chart/defaults.d.ts +5 -0
  12. package/dist/src/defineCanvasLayer.d.ts +16 -0
  13. package/dist/src/defineCanvasPlugin.d.ts +22 -0
  14. package/dist/src/defineSVGLayer.d.ts +16 -0
  15. package/dist/src/defineSVGPlugin.d.ts +22 -0
  16. package/dist/src/index.d.ts +6 -14
  17. package/dist/src/layer/createLayer.d.ts +3 -0
  18. package/dist/src/plugin/createPlugin.d.ts +3 -0
  19. package/dist/src/test/createGraphData.test.d.ts +1 -0
  20. package/dist/src/test/createTreeData.test.d.ts +1 -0
  21. package/dist/src/test/simple-graph-test.d.ts +74 -0
  22. package/dist/src/test/simple-tree-test.d.ts +13 -0
  23. package/dist/src/types/Chart.d.ts +39 -0
  24. package/dist/src/types/ChartContext.d.ts +27 -0
  25. package/dist/src/types/Common.d.ts +3 -0
  26. package/dist/src/types/Encoding.d.ts +33 -0
  27. package/dist/src/types/Event.d.ts +12 -0
  28. package/dist/src/types/Layers.d.ts +55 -0
  29. package/dist/src/types/ModelData.d.ts +70 -0
  30. package/dist/src/types/Plugin.d.ts +39 -0
  31. package/dist/src/types/RawData.d.ts +18 -0
  32. package/dist/src/types/RenderData.d.ts +4 -0
  33. package/dist/src/types/Theme.d.ts +17 -0
  34. package/dist/src/types/Validator.d.ts +20 -0
  35. package/dist/src/types/index.d.ts +12 -0
  36. package/dist/src/utils/aggregateUtils.d.ts +37 -0
  37. package/dist/src/utils/colorUtils.d.ts +22 -0
  38. package/dist/src/utils/commonUtils.d.ts +3 -5
  39. package/dist/src/utils/dom-lifecycle.d.ts +37 -0
  40. package/dist/src/utils/dom.d.ts +6 -0
  41. package/dist/src/utils/index.d.ts +5 -1
  42. package/dist/src/utils/observables.d.ts +1 -25
  43. package/dist/src/utils/orbchartsUtils.d.ts +2 -53
  44. package/dist/src/utils/validator.d.ts +2 -2
  45. package/dist/test/aggregateTest.d.ts +1 -0
  46. package/package.json +59 -46
  47. package/src/OrbCharts.ts +35 -0
  48. package/src/chart/createChart.ts +997 -0
  49. package/src/chart/createGraphData.ts +391 -0
  50. package/src/chart/createGridData.ts +247 -0
  51. package/src/chart/createMultivariateData.ts +181 -0
  52. package/src/chart/createSeriesData.ts +297 -0
  53. package/src/chart/createTreeData.ts +344 -0
  54. package/src/chart/defaults.ts +100 -0
  55. package/src/defineCanvasLayer.ts +24 -0
  56. package/src/defineCanvasPlugin.ts +39 -0
  57. package/src/defineSVGLayer.ts +24 -0
  58. package/src/defineSVGPlugin.ts +39 -0
  59. package/src/index.ts +8 -20
  60. package/src/layer/createLayer.ts +138 -0
  61. package/src/plugin/createPlugin.ts +470 -0
  62. package/src/test/createGraphData.test.ts +103 -0
  63. package/src/test/createTreeData.test.ts +97 -0
  64. package/src/test/simple-graph-test.js +51 -0
  65. package/src/test/simple-tree-test.js +58 -0
  66. package/src/types/Chart.ts +62 -0
  67. package/src/types/ChartContext.ts +42 -0
  68. package/src/types/Common.ts +5 -0
  69. package/src/types/Encoding.ts +43 -0
  70. package/src/types/Event.ts +26 -0
  71. package/src/types/Layers.ts +93 -0
  72. package/src/types/ModelData.ts +95 -0
  73. package/src/types/Plugin.ts +98 -0
  74. package/src/types/RawData.ts +67 -0
  75. package/src/types/RenderData.ts +16 -0
  76. package/src/types/Theme.ts +21 -0
  77. package/src/types/Validator.ts +36 -0
  78. package/src/types/index.ts +12 -0
  79. package/src/utils/aggregateUtils.ts +99 -0
  80. package/src/utils/colorUtils.ts +63 -0
  81. package/src/utils/commonUtils.ts +56 -55
  82. package/src/utils/dom-lifecycle.ts +164 -0
  83. package/src/utils/dom.ts +55 -0
  84. package/src/utils/errorMessage.ts +40 -40
  85. package/src/utils/index.ts +8 -4
  86. package/src/utils/observables.ts +16 -308
  87. package/src/utils/orbchartsUtils.ts +9 -396
  88. package/src/utils/validator.ts +127 -126
  89. package/dist/lib/core-types.d.ts +0 -1
  90. package/dist/src/AbstractChart.d.ts +0 -19
  91. package/dist/src/GridChart.d.ts +0 -6
  92. package/dist/src/MultiGridChart.d.ts +0 -6
  93. package/dist/src/MultiValueChart.d.ts +0 -6
  94. package/dist/src/RelationshipChart.d.ts +0 -6
  95. package/dist/src/SeriesChart.d.ts +0 -6
  96. package/dist/src/TreeChart.d.ts +0 -6
  97. package/dist/src/base/createBaseChart.d.ts +0 -3
  98. package/dist/src/base/createBasePlugin.d.ts +0 -3
  99. package/dist/src/base/validators/chartOptionsValidator.d.ts +0 -3
  100. package/dist/src/base/validators/chartParamsValidator.d.ts +0 -3
  101. package/dist/src/base/validators/elementValidator.d.ts +0 -3
  102. package/dist/src/base/validators/pluginsValidator.d.ts +0 -3
  103. package/dist/src/defaults.d.ts +0 -25
  104. package/dist/src/defineGridPlugin.d.ts +0 -1
  105. package/dist/src/defineMultiGridPlugin.d.ts +0 -1
  106. package/dist/src/defineMultiValuePlugin.d.ts +0 -1
  107. package/dist/src/defineNoneDataPlugin.d.ts +0 -1
  108. package/dist/src/defineRelationshipPlugin.d.ts +0 -1
  109. package/dist/src/defineSeriesPlugin.d.ts +0 -1
  110. package/dist/src/defineTreePlugin.d.ts +0 -1
  111. package/dist/src/grid/computedDataFn.d.ts +0 -4
  112. package/dist/src/grid/contextObserverCallback.d.ts +0 -3
  113. package/dist/src/grid/dataFormatterValidator.d.ts +0 -3
  114. package/dist/src/grid/dataValidator.d.ts +0 -3
  115. package/dist/src/grid/gridObservables.d.ts +0 -64
  116. package/dist/src/multiGrid/computedDataFn.d.ts +0 -3
  117. package/dist/src/multiGrid/contextObserverCallback.d.ts +0 -3
  118. package/dist/src/multiGrid/dataFormatterValidator.d.ts +0 -3
  119. package/dist/src/multiGrid/dataValidator.d.ts +0 -3
  120. package/dist/src/multiGrid/multiGridObservables.d.ts +0 -16
  121. package/dist/src/multiValue/computedDataFn.d.ts +0 -3
  122. package/dist/src/multiValue/contextObserverCallback.d.ts +0 -3
  123. package/dist/src/multiValue/dataFormatterValidator.d.ts +0 -3
  124. package/dist/src/multiValue/dataValidator.d.ts +0 -3
  125. package/dist/src/multiValue/multiValueObservables.d.ts +0 -130
  126. package/dist/src/relationship/computedDataFn.d.ts +0 -3
  127. package/dist/src/relationship/contextObserverCallback.d.ts +0 -3
  128. package/dist/src/relationship/dataFormatterValidator.d.ts +0 -3
  129. package/dist/src/relationship/dataValidator.d.ts +0 -3
  130. package/dist/src/relationship/relationshipObservables.d.ts +0 -13
  131. package/dist/src/series/computedDataFn.d.ts +0 -3
  132. package/dist/src/series/contextObserverCallback.d.ts +0 -3
  133. package/dist/src/series/dataFormatterValidator.d.ts +0 -3
  134. package/dist/src/series/dataValidator.d.ts +0 -3
  135. package/dist/src/series/seriesObservables.d.ts +0 -37
  136. package/dist/src/tree/computedDataFn.d.ts +0 -3
  137. package/dist/src/tree/contextObserverCallback.d.ts +0 -3
  138. package/dist/src/tree/dataFormatterValidator.d.ts +0 -3
  139. package/dist/src/tree/dataValidator.d.ts +0 -3
  140. package/dist/src/tree/treeObservables.d.ts +0 -10
  141. package/dist/src/utils/d3Scale.d.ts +0 -28
  142. package/lib/core-types.ts +0 -7
  143. package/src/AbstractChart.ts +0 -57
  144. package/src/GridChart.ts +0 -25
  145. package/src/MultiGridChart.ts +0 -25
  146. package/src/MultiValueChart.ts +0 -25
  147. package/src/RelationshipChart.ts +0 -25
  148. package/src/SeriesChart.ts +0 -25
  149. package/src/TreeChart.ts +0 -25
  150. package/src/base/createBaseChart.ts +0 -524
  151. package/src/base/createBasePlugin.ts +0 -154
  152. package/src/base/validators/chartOptionsValidator.ts +0 -24
  153. package/src/base/validators/chartParamsValidator.ts +0 -134
  154. package/src/base/validators/elementValidator.ts +0 -14
  155. package/src/base/validators/pluginsValidator.ts +0 -15
  156. package/src/defaults.ts +0 -284
  157. package/src/defineGridPlugin.ts +0 -3
  158. package/src/defineMultiGridPlugin.ts +0 -3
  159. package/src/defineMultiValuePlugin.ts +0 -3
  160. package/src/defineNoneDataPlugin.ts +0 -4
  161. package/src/defineRelationshipPlugin.ts +0 -3
  162. package/src/defineSeriesPlugin.ts +0 -3
  163. package/src/defineTreePlugin.ts +0 -3
  164. package/src/grid/computedDataFn.ts +0 -129
  165. package/src/grid/contextObserverCallback.ts +0 -209
  166. package/src/grid/dataFormatterValidator.ts +0 -126
  167. package/src/grid/dataValidator.ts +0 -13
  168. package/src/grid/gridObservables.ts +0 -699
  169. package/src/multiGrid/computedDataFn.ts +0 -123
  170. package/src/multiGrid/contextObserverCallback.ts +0 -109
  171. package/src/multiGrid/dataFormatterValidator.ts +0 -121
  172. package/src/multiGrid/dataValidator.ts +0 -13
  173. package/src/multiGrid/multiGridObservables.ts +0 -367
  174. package/src/multiValue/computedDataFn.ts +0 -113
  175. package/src/multiValue/contextObserverCallback.ts +0 -328
  176. package/src/multiValue/dataFormatterValidator.ts +0 -95
  177. package/src/multiValue/dataValidator.ts +0 -13
  178. package/src/multiValue/multiValueObservables.ts +0 -865
  179. package/src/relationship/computedDataFn.ts +0 -159
  180. package/src/relationship/contextObserverCallback.ts +0 -80
  181. package/src/relationship/dataFormatterValidator.ts +0 -14
  182. package/src/relationship/dataValidator.ts +0 -14
  183. package/src/relationship/relationshipObservables.ts +0 -85
  184. package/src/series/computedDataFn.ts +0 -88
  185. package/src/series/contextObserverCallback.ts +0 -132
  186. package/src/series/dataFormatterValidator.ts +0 -47
  187. package/src/series/dataValidator.ts +0 -13
  188. package/src/series/seriesObservables.ts +0 -210
  189. package/src/tree/computedDataFn.ts +0 -129
  190. package/src/tree/contextObserverCallback.ts +0 -58
  191. package/src/tree/dataFormatterValidator.ts +0 -14
  192. package/src/tree/dataValidator.ts +0 -14
  193. package/src/tree/treeObservables.ts +0 -106
  194. package/src/utils/d3Scale.ts +0 -198
  195. package/tsconfig.base.json +0 -14
  196. package/tsconfig.json +0 -3
  197. package/vite-env.d.ts +0 -7
  198. 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
+ }
@@ -1,55 +1,56 @@
1
-
2
- // 是否為原始物件
3
- export function isPlainObject(variable: any) {
4
- return Object.prototype.toString.call(variable) === "[object Object]";
5
- }
6
-
7
- // 是否為function
8
- export function isFunction(fn: any) {
9
- // return !!fn && !fn.nodename && fn.constructor != String && fn.constructor != RegExp && fn.constructor != Array && /function/i.test(fn + "");
10
- return Object.prototype.toString.call(fn) === '[object Function]'
11
- }
12
-
13
- // 是否為dom
14
- export function isDom(obj: any) {
15
- return !!(obj && obj.nodeType);
16
- }
17
-
18
- // 將可選的參數和預設值合併
19
- export function mergeOptionsWithDefault<Options extends { [key: string]: any; }> (options: {[key: string]: any}, defaultOptions: Options): Options {
20
- if (isPlainObject(options) === false || isPlainObject(defaultOptions) === false) {
21
- return Object.assign({}, defaultOptions)
22
- }
23
- const mergeObjColumns = (_options: {[key: string]: any}, _defaultOptions: {[key: string]: any}) => {
24
- const obj: Options = (Object.assign({}, _defaultOptions) as any)
25
- for (let key of Object.keys(_options)) {
26
- if ((key in _defaultOptions) == false) {
27
- continue
28
- }
29
- let objValue: any = undefined
30
- // 下一層的plain object
31
- if (isPlainObject(_options[key]) && isPlainObject(_defaultOptions[key])) {
32
- objValue = mergeObjColumns(_options[key], _defaultOptions[key])
33
- obj[key as keyof Options] = objValue
34
- }
35
- // 不是plain object直接賦值
36
- else {
37
- obj[key as keyof Options] = _options[key]
38
- }
39
- }
40
- return obj
41
- }
42
-
43
- return mergeObjColumns(options, defaultOptions)
44
- }
45
-
46
- // 加上千分位 ,
47
- export function formatCommaNumber (num = 0): string {
48
- try {
49
- let parts = num.toString().split('.');
50
- parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
51
- return parts.join('.');
52
- } catch (e: any) {
53
- console.error(e)
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
+ }