@pyreon/charts 0.9.0 → 0.11.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 (42) hide show
  1. package/lib/analysis/index.js.html +1 -1
  2. package/lib/analysis/manual.js.html +1 -1
  3. package/lib/{charts-Ckh2qxB5.js → charts-lo2KeDld.js} +164 -164
  4. package/lib/charts-lo2KeDld.js.map +1 -0
  5. package/lib/{components-BcPePBeS.js → components-ClWy1Ztp.js} +128 -128
  6. package/lib/components-ClWy1Ztp.js.map +1 -0
  7. package/lib/{core-9w0g6EOI.js → core-BiuQ3y-t.js} +11 -11
  8. package/lib/core-BiuQ3y-t.js.map +1 -0
  9. package/lib/{createSeriesData-DOHScdgk.js → createSeriesData-BGy-6PqI.js} +6 -6
  10. package/lib/createSeriesData-BGy-6PqI.js.map +1 -0
  11. package/lib/{customGraphicKeyframeAnimation-CvkEkSt_.js → customGraphicKeyframeAnimation-BIbJI8ew.js} +61 -61
  12. package/lib/customGraphicKeyframeAnimation-BIbJI8ew.js.map +1 -0
  13. package/lib/{graphic-CPJ2K90a.js → graphic-Bt7SEwll.js} +59 -59
  14. package/lib/graphic-Bt7SEwll.js.map +1 -0
  15. package/lib/index.js +60 -52
  16. package/lib/index.js.map +1 -1
  17. package/lib/manual.js +60 -52
  18. package/lib/manual.js.map +1 -1
  19. package/lib/{parseGeoJson-BlBe5Vig.js → parseGeoJson-NjUY1feF.js} +115 -115
  20. package/lib/parseGeoJson-NjUY1feF.js.map +1 -0
  21. package/lib/{renderers-Dytryvoy.js → renderers-BnAAXHfG.js} +16 -16
  22. package/lib/renderers-BnAAXHfG.js.map +1 -0
  23. package/lib/types/index.d.ts +3 -3
  24. package/lib/types/index.d.ts.map +1 -1
  25. package/lib/types/manual.d.ts +3 -3
  26. package/lib/types/manual.d.ts.map +1 -1
  27. package/package.json +14 -7
  28. package/src/chart-component.tsx +18 -10
  29. package/src/index.ts +3 -3
  30. package/src/loader.ts +70 -73
  31. package/src/manual.ts +4 -4
  32. package/src/tests/charts.test.tsx +431 -126
  33. package/src/types.ts +8 -9
  34. package/src/use-chart.ts +8 -8
  35. package/lib/charts-Ckh2qxB5.js.map +0 -1
  36. package/lib/components-BcPePBeS.js.map +0 -1
  37. package/lib/core-9w0g6EOI.js.map +0 -1
  38. package/lib/createSeriesData-DOHScdgk.js.map +0 -1
  39. package/lib/customGraphicKeyframeAnimation-CvkEkSt_.js.map +0 -1
  40. package/lib/graphic-CPJ2K90a.js.map +0 -1
  41. package/lib/parseGeoJson-BlBe5Vig.js.map +0 -1
  42. package/lib/renderers-Dytryvoy.js.map +0 -1
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@pyreon/charts",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Reactive ECharts bridge for Pyreon — lazy loading, signal-driven, Canvas by default",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/pyreon/fundamentals.git",
9
- "directory": "packages/charts"
8
+ "url": "https://github.com/pyreon/pyreon.git",
9
+ "directory": "packages/fundamentals/charts"
10
10
  },
11
11
  "homepage": "https://github.com/pyreon/fundamentals/tree/main/packages/charts#readme",
12
12
  "bugs": {
13
- "url": "https://github.com/pyreon/fundamentals/issues"
13
+ "url": "https://github.com/pyreon/pyreon/issues"
14
14
  },
15
15
  "publishConfig": {
16
16
  "access": "public"
@@ -42,11 +42,18 @@
42
42
  "build": "vl_rolldown_build",
43
43
  "dev": "vl_rolldown_build-watch",
44
44
  "test": "vitest run",
45
- "typecheck": "tsc --noEmit"
45
+ "typecheck": "tsc --noEmit",
46
+ "lint": "biome check ."
46
47
  },
47
48
  "peerDependencies": {
48
- "@pyreon/core": ">=0.7.0 <0.8.0",
49
- "@pyreon/reactivity": ">=0.7.0 <0.8.0",
49
+ "@pyreon/core": "^0.11.0",
50
+ "@pyreon/reactivity": "^0.11.0",
50
51
  "echarts": ">=5.6.0"
52
+ },
53
+ "devDependencies": {
54
+ "@pyreon/core": "^0.11.0",
55
+ "@pyreon/reactivity": "^0.11.0",
56
+ "@pyreon/runtime-dom": "^0.11.0",
57
+ "echarts": "^6.0.0"
51
58
  }
52
59
  }
@@ -1,8 +1,15 @@
1
- import type { VNodeChild } from '@pyreon/core'
2
- import { effect } from '@pyreon/reactivity'
3
- import type { EChartsOption } from 'echarts'
4
- import type { ChartProps } from './types'
5
- import { useChart } from './use-chart'
1
+ import type { VNodeChild } from "@pyreon/core"
2
+ import { effect } from "@pyreon/reactivity"
3
+ import type { EChartsOption } from "echarts"
4
+ import type { ECElementEvent } from "echarts/core"
5
+ import type { ChartProps } from "./types"
6
+ import { useChart } from "./use-chart"
7
+
8
+ /**
9
+ * Handler type that bridges our duck-typed ChartEventParams with
10
+ * echarts' internal ECElementEvent. Used for event binding casts.
11
+ */
12
+ type ECHandler = (params: ECElementEvent) => boolean | undefined
6
13
 
7
14
  /**
8
15
  * Reactive chart component. Wraps useChart in a div with automatic
@@ -42,11 +49,12 @@ export function Chart<TOption extends EChartsOption = EChartsOption>(
42
49
  const inst = chart.instance()
43
50
  if (!inst) return
44
51
 
45
- // Handlers are duck-typed ChartEventParams — cast needed because
46
- // echarts/core and echarts export incompatible private class types
47
- if (props.onClick) inst.on('click', props.onClick as any)
48
- if (props.onMouseover) inst.on('mouseover', props.onMouseover as any)
49
- if (props.onMouseout) inst.on('mouseout', props.onMouseout as any)
52
+ // Handlers are duck-typed ChartEventParams — cast through unknown
53
+ // to ECHandler because echarts/core and echarts export incompatible
54
+ // private class types for ECElementEvent.
55
+ if (props.onClick) inst.on("click", props.onClick as unknown as ECHandler)
56
+ if (props.onMouseover) inst.on("mouseover", props.onMouseover as unknown as ECHandler)
57
+ if (props.onMouseout) inst.on("mouseout", props.onMouseout as unknown as ECHandler)
50
58
  })
51
59
 
52
60
  return () => <div ref={chart.ref} style={props.style} class={props.class} />
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@
22
22
  * ```
23
23
  */
24
24
 
25
- export { Chart } from './chart-component'
25
+ export { Chart } from "./chart-component"
26
26
  // Chart configuration types
27
27
  // Re-exported ECharts types for consumer convenience —
28
28
  // consumers get full autocomplete without importing echarts directly
@@ -60,5 +60,5 @@ export type {
60
60
  UseChartConfig,
61
61
  UseChartResult,
62
62
  VisualMapComponentOption,
63
- } from './types'
64
- export { useChart } from './use-chart'
63
+ } from "./types"
64
+ export { useChart } from "./use-chart"
package/src/loader.ts CHANGED
@@ -16,86 +16,86 @@ type LooseOption = Record<string, unknown> & {
16
16
 
17
17
  type ModuleLoader = () => Promise<unknown>
18
18
 
19
+ /** The argument type that `echarts/core.use()` accepts. */
20
+ type EChartsUseArg = Parameters<typeof import("echarts/core").use>[0]
21
+
19
22
  // ─── Chart type mapping ─────────────────────────────────────────────────────
20
23
 
21
24
  const CHARTS: Record<string, ModuleLoader> = {
22
- bar: () => import('echarts/charts').then((m) => m.BarChart),
23
- line: () => import('echarts/charts').then((m) => m.LineChart),
24
- pie: () => import('echarts/charts').then((m) => m.PieChart),
25
- scatter: () => import('echarts/charts').then((m) => m.ScatterChart),
26
- radar: () => import('echarts/charts').then((m) => m.RadarChart),
27
- heatmap: () => import('echarts/charts').then((m) => m.HeatmapChart),
28
- treemap: () => import('echarts/charts').then((m) => m.TreemapChart),
29
- sunburst: () => import('echarts/charts').then((m) => m.SunburstChart),
30
- sankey: () => import('echarts/charts').then((m) => m.SankeyChart),
31
- funnel: () => import('echarts/charts').then((m) => m.FunnelChart),
32
- gauge: () => import('echarts/charts').then((m) => m.GaugeChart),
33
- graph: () => import('echarts/charts').then((m) => m.GraphChart),
34
- tree: () => import('echarts/charts').then((m) => m.TreeChart),
35
- boxplot: () => import('echarts/charts').then((m) => m.BoxplotChart),
36
- candlestick: () => import('echarts/charts').then((m) => m.CandlestickChart),
37
- parallel: () => import('echarts/charts').then((m) => m.ParallelChart),
38
- themeRiver: () => import('echarts/charts').then((m) => m.ThemeRiverChart),
39
- effectScatter: () =>
40
- import('echarts/charts').then((m) => m.EffectScatterChart),
41
- lines: () => import('echarts/charts').then((m) => m.LinesChart),
42
- pictorialBar: () => import('echarts/charts').then((m) => m.PictorialBarChart),
43
- custom: () => import('echarts/charts').then((m) => m.CustomChart),
44
- map: () => import('echarts/charts').then((m) => m.MapChart),
25
+ bar: () => import("echarts/charts").then((m) => m.BarChart),
26
+ line: () => import("echarts/charts").then((m) => m.LineChart),
27
+ pie: () => import("echarts/charts").then((m) => m.PieChart),
28
+ scatter: () => import("echarts/charts").then((m) => m.ScatterChart),
29
+ radar: () => import("echarts/charts").then((m) => m.RadarChart),
30
+ heatmap: () => import("echarts/charts").then((m) => m.HeatmapChart),
31
+ treemap: () => import("echarts/charts").then((m) => m.TreemapChart),
32
+ sunburst: () => import("echarts/charts").then((m) => m.SunburstChart),
33
+ sankey: () => import("echarts/charts").then((m) => m.SankeyChart),
34
+ funnel: () => import("echarts/charts").then((m) => m.FunnelChart),
35
+ gauge: () => import("echarts/charts").then((m) => m.GaugeChart),
36
+ graph: () => import("echarts/charts").then((m) => m.GraphChart),
37
+ tree: () => import("echarts/charts").then((m) => m.TreeChart),
38
+ boxplot: () => import("echarts/charts").then((m) => m.BoxplotChart),
39
+ candlestick: () => import("echarts/charts").then((m) => m.CandlestickChart),
40
+ parallel: () => import("echarts/charts").then((m) => m.ParallelChart),
41
+ themeRiver: () => import("echarts/charts").then((m) => m.ThemeRiverChart),
42
+ effectScatter: () => import("echarts/charts").then((m) => m.EffectScatterChart),
43
+ lines: () => import("echarts/charts").then((m) => m.LinesChart),
44
+ pictorialBar: () => import("echarts/charts").then((m) => m.PictorialBarChart),
45
+ custom: () => import("echarts/charts").then((m) => m.CustomChart),
46
+ map: () => import("echarts/charts").then((m) => m.MapChart),
45
47
  }
46
48
 
47
49
  // ─── Component mapping ──────────────────────────────────────────────────────
48
50
 
49
51
  // Multiple config keys can map to the same component (xAxis/yAxis → Grid)
50
52
  const COMPONENTS: Record<string, ModuleLoader> = {
51
- grid: () => import('echarts/components').then((m) => m.GridComponent),
52
- xAxis: () => import('echarts/components').then((m) => m.GridComponent),
53
- yAxis: () => import('echarts/components').then((m) => m.GridComponent),
54
- polar: () => import('echarts/components').then((m) => m.PolarComponent),
55
- radar: () => import('echarts/components').then((m) => m.RadarComponent),
56
- geo: () => import('echarts/components').then((m) => m.GeoComponent),
57
- tooltip: () => import('echarts/components').then((m) => m.TooltipComponent),
58
- legend: () => import('echarts/components').then((m) => m.LegendComponent),
59
- toolbox: () => import('echarts/components').then((m) => m.ToolboxComponent),
60
- title: () => import('echarts/components').then((m) => m.TitleComponent),
61
- dataZoom: () => import('echarts/components').then((m) => m.DataZoomComponent),
62
- visualMap: () =>
63
- import('echarts/components').then((m) => m.VisualMapComponent),
64
- timeline: () => import('echarts/components').then((m) => m.TimelineComponent),
65
- graphic: () => import('echarts/components').then((m) => m.GraphicComponent),
66
- brush: () => import('echarts/components').then((m) => m.BrushComponent),
67
- calendar: () => import('echarts/components').then((m) => m.CalendarComponent),
68
- dataset: () => import('echarts/components').then((m) => m.DatasetComponent),
69
- aria: () => import('echarts/components').then((m) => m.AriaComponent),
53
+ grid: () => import("echarts/components").then((m) => m.GridComponent),
54
+ xAxis: () => import("echarts/components").then((m) => m.GridComponent),
55
+ yAxis: () => import("echarts/components").then((m) => m.GridComponent),
56
+ polar: () => import("echarts/components").then((m) => m.PolarComponent),
57
+ radar: () => import("echarts/components").then((m) => m.RadarComponent),
58
+ geo: () => import("echarts/components").then((m) => m.GeoComponent),
59
+ tooltip: () => import("echarts/components").then((m) => m.TooltipComponent),
60
+ legend: () => import("echarts/components").then((m) => m.LegendComponent),
61
+ toolbox: () => import("echarts/components").then((m) => m.ToolboxComponent),
62
+ title: () => import("echarts/components").then((m) => m.TitleComponent),
63
+ dataZoom: () => import("echarts/components").then((m) => m.DataZoomComponent),
64
+ visualMap: () => import("echarts/components").then((m) => m.VisualMapComponent),
65
+ timeline: () => import("echarts/components").then((m) => m.TimelineComponent),
66
+ graphic: () => import("echarts/components").then((m) => m.GraphicComponent),
67
+ brush: () => import("echarts/components").then((m) => m.BrushComponent),
68
+ calendar: () => import("echarts/components").then((m) => m.CalendarComponent),
69
+ dataset: () => import("echarts/components").then((m) => m.DatasetComponent),
70
+ aria: () => import("echarts/components").then((m) => m.AriaComponent),
70
71
  }
71
72
 
72
73
  // Series-level features
73
74
  const SERIES_FEATURES: Record<string, ModuleLoader> = {
74
- markPoint: () =>
75
- import('echarts/components').then((m) => m.MarkPointComponent),
76
- markLine: () => import('echarts/components').then((m) => m.MarkLineComponent),
77
- markArea: () => import('echarts/components').then((m) => m.MarkAreaComponent),
75
+ markPoint: () => import("echarts/components").then((m) => m.MarkPointComponent),
76
+ markLine: () => import("echarts/components").then((m) => m.MarkLineComponent),
77
+ markArea: () => import("echarts/components").then((m) => m.MarkAreaComponent),
78
78
  }
79
79
 
80
80
  // ─── Renderers ──────────────────────────────────────────────────────────────
81
81
 
82
82
  const RENDERERS: Record<string, ModuleLoader> = {
83
- canvas: () => import('echarts/renderers').then((m) => m.CanvasRenderer),
84
- svg: () => import('echarts/renderers').then((m) => m.SVGRenderer),
83
+ canvas: () => import("echarts/renderers").then((m) => m.CanvasRenderer),
84
+ svg: () => import("echarts/renderers").then((m) => m.SVGRenderer),
85
85
  }
86
86
 
87
87
  // ─── Core loading ───────────────────────────────────────────────────────────
88
88
 
89
- let coreModule: typeof import('echarts/core') | null = null
90
- let corePromise: Promise<typeof import('echarts/core')> | null = null
89
+ let coreModule: typeof import("echarts/core") | null = null
90
+ let corePromise: Promise<typeof import("echarts/core")> | null = null
91
91
 
92
92
  /**
93
93
  * Lazily load echarts/core. Cached after first call.
94
94
  */
95
- export async function getCore(): Promise<typeof import('echarts/core')> {
95
+ export async function getCore(): Promise<typeof import("echarts/core")> {
96
96
  if (coreModule) return coreModule
97
97
  if (!corePromise) {
98
- corePromise = import('echarts/core').then((m) => {
98
+ corePromise = import("echarts/core").then((m) => {
99
99
  coreModule = m
100
100
  return m
101
101
  })
@@ -106,7 +106,7 @@ export async function getCore(): Promise<typeof import('echarts/core')> {
106
106
  /**
107
107
  * Get the cached core module (null if not yet loaded).
108
108
  */
109
- export function getCoreSync(): typeof import('echarts/core') | null {
109
+ export function getCoreSync(): typeof import("echarts/core") | null {
110
110
  return coreModule
111
111
  }
112
112
 
@@ -116,7 +116,7 @@ const registered = new Set<string>()
116
116
  const inflight = new Map<string, Promise<void>>()
117
117
 
118
118
  async function loadAndRegister(
119
- core: typeof import('echarts/core'),
119
+ core: typeof import("echarts/core"),
120
120
  key: string,
121
121
  loader: ModuleLoader,
122
122
  ): Promise<void> {
@@ -124,7 +124,7 @@ async function loadAndRegister(
124
124
  if (inflight.has(key)) return inflight.get(key)
125
125
 
126
126
  const promise = loader().then((mod) => {
127
- core.use(mod as any)
127
+ core.use(mod as EChartsUseArg)
128
128
  registered.add(key)
129
129
  inflight.delete(key)
130
130
  })
@@ -139,47 +139,44 @@ async function loadAndRegister(
139
139
  */
140
140
  export async function ensureModules(
141
141
  option: LooseOption,
142
- renderer: 'canvas' | 'svg' = 'canvas',
143
- ): Promise<typeof import('echarts/core')> {
142
+ renderer: "canvas" | "svg" = "canvas",
143
+ ): Promise<typeof import("echarts/core")> {
144
144
  const core = await getCore()
145
145
  const loads: Promise<void>[] = []
146
146
 
147
147
  // Renderer (always needed)
148
- loads.push(
149
- loadAndRegister(core, `renderer:${renderer}`, RENDERERS[renderer]!),
150
- )
148
+ const rendererLoader = RENDERERS[renderer]
149
+ if (rendererLoader) loads.push(loadAndRegister(core, `renderer:${renderer}`, rendererLoader))
151
150
 
152
151
  // Normalize series to array for analysis
153
152
  const rawSeries = option.series
154
153
  const seriesList: Record<string, unknown>[] = rawSeries
155
- ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<
156
- string,
157
- unknown
158
- >[])
154
+ ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<string, unknown>[])
159
155
  : []
160
156
 
161
157
  // Chart types from series[].type
162
158
  for (const s of seriesList) {
163
159
  const type = s.type as string | undefined
164
- if (type && CHARTS[type]) {
165
- loads.push(loadAndRegister(core, `chart:${type}`, CHARTS[type]!))
160
+ const chartLoader = type ? CHARTS[type] : undefined
161
+ if (chartLoader) {
162
+ loads.push(loadAndRegister(core, `chart:${type}`, chartLoader))
166
163
  }
167
164
  }
168
165
 
169
166
  // Components from top-level config keys
170
167
  for (const key of Object.keys(option)) {
171
- if (COMPONENTS[key]) {
172
- loads.push(loadAndRegister(core, `component:${key}`, COMPONENTS[key]!))
168
+ const compLoader = COMPONENTS[key]
169
+ if (compLoader) {
170
+ loads.push(loadAndRegister(core, `component:${key}`, compLoader))
173
171
  }
174
172
  }
175
173
 
176
174
  // Series-level features (markPoint, markLine, markArea)
177
175
  for (const s of seriesList) {
178
176
  for (const key of Object.keys(s)) {
179
- if (SERIES_FEATURES[key]) {
180
- loads.push(
181
- loadAndRegister(core, `feature:${key}`, SERIES_FEATURES[key]!),
182
- )
177
+ const featureLoader = SERIES_FEATURES[key]
178
+ if (featureLoader) {
179
+ loads.push(loadAndRegister(core, `feature:${key}`, featureLoader))
183
180
  }
184
181
  }
185
182
  }
@@ -205,7 +202,7 @@ export async function ensureModules(
205
202
  export function manualUse(...modules: unknown[]): void {
206
203
  const core = getCoreSync()
207
204
  if (core) {
208
- core.use(modules as any)
205
+ core.use(modules as EChartsUseArg)
209
206
  } else {
210
207
  // Core not loaded yet — queue for when it loads
211
208
  getCore().then((c) => c.use(modules as any))
package/src/manual.ts CHANGED
@@ -25,12 +25,12 @@
25
25
  * ```
26
26
  */
27
27
 
28
- export { Chart } from './chart-component'
29
- export { manualUse as use } from './loader'
28
+ export { Chart } from "./chart-component"
29
+ export { manualUse as use } from "./loader"
30
30
  export type {
31
31
  ChartProps,
32
32
  EChartsOption,
33
33
  UseChartConfig,
34
34
  UseChartResult,
35
- } from './types'
36
- export { useChart } from './use-chart'
35
+ } from "./types"
36
+ export { useChart } from "./use-chart"