@pyreon/charts 0.6.0 → 0.8.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/lib/index.js CHANGED
@@ -153,10 +153,10 @@ function useChart(optionsFn, config) {
153
153
  try {
154
154
  const chart = core.init(el, config?.theme, {
155
155
  renderer,
156
- locale: config?.locale,
157
- devicePixelRatio: config?.devicePixelRatio,
158
- width: config?.width,
159
- height: config?.height
156
+ ...config?.locale != null ? { locale: config.locale } : {},
157
+ ...config?.devicePixelRatio != null ? { devicePixelRatio: config.devicePixelRatio } : {},
158
+ ...config?.width != null ? { width: config.width } : {},
159
+ ...config?.height != null ? { height: config.height } : {}
160
160
  });
161
161
  chart.setOption(opts);
162
162
  instance.set(chart);
@@ -210,7 +210,7 @@ function useChart(optionsFn, config) {
210
210
  }
211
211
 
212
212
  //#endregion
213
- //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
213
+ //#region ../../node_modules/.bun/@pyreon+core@0.7.3/node_modules/@pyreon/core/lib/jsx-runtime.js
214
214
  /**
215
215
  * Hyperscript function — the compiled output of JSX.
216
216
  * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
@@ -287,8 +287,8 @@ function jsx(type, props, key) {
287
287
  */
288
288
  function Chart(props) {
289
289
  const chart = useChart(props.options, {
290
- theme: props.theme,
291
- renderer: props.renderer
290
+ ...props.theme != null ? { theme: props.theme } : {},
291
+ ...props.renderer != null ? { renderer: props.renderer } : {}
292
292
  });
293
293
  effect(() => {
294
294
  const inst = chart.instance();
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/loader.ts","../src/use-chart.ts","../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/chart-component.tsx"],"sourcesContent":["/**\n * Lazy loading and auto-detection for ECharts modules.\n *\n * Maps config keys to ECharts modular imports. Only loads what's needed,\n * caches after first load. The echarts/core module itself is lazy-loaded\n * on first use — zero ECharts bytes until a chart actually renders.\n */\n\n/**\n * Loose option type for internal module analysis.\n * The strict EChartsOption type is used at the consumer-facing API level.\n */\ntype LooseOption = Record<string, unknown> & {\n series?: unknown\n}\n\ntype ModuleLoader = () => Promise<unknown>\n\n// ─── Chart type mapping ─────────────────────────────────────────────────────\n\nconst CHARTS: Record<string, ModuleLoader> = {\n bar: () => import('echarts/charts').then((m) => m.BarChart),\n line: () => import('echarts/charts').then((m) => m.LineChart),\n pie: () => import('echarts/charts').then((m) => m.PieChart),\n scatter: () => import('echarts/charts').then((m) => m.ScatterChart),\n radar: () => import('echarts/charts').then((m) => m.RadarChart),\n heatmap: () => import('echarts/charts').then((m) => m.HeatmapChart),\n treemap: () => import('echarts/charts').then((m) => m.TreemapChart),\n sunburst: () => import('echarts/charts').then((m) => m.SunburstChart),\n sankey: () => import('echarts/charts').then((m) => m.SankeyChart),\n funnel: () => import('echarts/charts').then((m) => m.FunnelChart),\n gauge: () => import('echarts/charts').then((m) => m.GaugeChart),\n graph: () => import('echarts/charts').then((m) => m.GraphChart),\n tree: () => import('echarts/charts').then((m) => m.TreeChart),\n boxplot: () => import('echarts/charts').then((m) => m.BoxplotChart),\n candlestick: () => import('echarts/charts').then((m) => m.CandlestickChart),\n parallel: () => import('echarts/charts').then((m) => m.ParallelChart),\n themeRiver: () => import('echarts/charts').then((m) => m.ThemeRiverChart),\n effectScatter: () =>\n import('echarts/charts').then((m) => m.EffectScatterChart),\n lines: () => import('echarts/charts').then((m) => m.LinesChart),\n pictorialBar: () => import('echarts/charts').then((m) => m.PictorialBarChart),\n custom: () => import('echarts/charts').then((m) => m.CustomChart),\n map: () => import('echarts/charts').then((m) => m.MapChart),\n}\n\n// ─── Component mapping ──────────────────────────────────────────────────────\n\n// Multiple config keys can map to the same component (xAxis/yAxis → Grid)\nconst COMPONENTS: Record<string, ModuleLoader> = {\n grid: () => import('echarts/components').then((m) => m.GridComponent),\n xAxis: () => import('echarts/components').then((m) => m.GridComponent),\n yAxis: () => import('echarts/components').then((m) => m.GridComponent),\n polar: () => import('echarts/components').then((m) => m.PolarComponent),\n radar: () => import('echarts/components').then((m) => m.RadarComponent),\n geo: () => import('echarts/components').then((m) => m.GeoComponent),\n tooltip: () => import('echarts/components').then((m) => m.TooltipComponent),\n legend: () => import('echarts/components').then((m) => m.LegendComponent),\n toolbox: () => import('echarts/components').then((m) => m.ToolboxComponent),\n title: () => import('echarts/components').then((m) => m.TitleComponent),\n dataZoom: () => import('echarts/components').then((m) => m.DataZoomComponent),\n visualMap: () =>\n import('echarts/components').then((m) => m.VisualMapComponent),\n timeline: () => import('echarts/components').then((m) => m.TimelineComponent),\n graphic: () => import('echarts/components').then((m) => m.GraphicComponent),\n brush: () => import('echarts/components').then((m) => m.BrushComponent),\n calendar: () => import('echarts/components').then((m) => m.CalendarComponent),\n dataset: () => import('echarts/components').then((m) => m.DatasetComponent),\n aria: () => import('echarts/components').then((m) => m.AriaComponent),\n}\n\n// Series-level features\nconst SERIES_FEATURES: Record<string, ModuleLoader> = {\n markPoint: () =>\n import('echarts/components').then((m) => m.MarkPointComponent),\n markLine: () => import('echarts/components').then((m) => m.MarkLineComponent),\n markArea: () => import('echarts/components').then((m) => m.MarkAreaComponent),\n}\n\n// ─── Renderers ──────────────────────────────────────────────────────────────\n\nconst RENDERERS: Record<string, ModuleLoader> = {\n canvas: () => import('echarts/renderers').then((m) => m.CanvasRenderer),\n svg: () => import('echarts/renderers').then((m) => m.SVGRenderer),\n}\n\n// ─── Core loading ───────────────────────────────────────────────────────────\n\nlet coreModule: typeof import('echarts/core') | null = null\nlet corePromise: Promise<typeof import('echarts/core')> | null = null\n\n/**\n * Lazily load echarts/core. Cached after first call.\n */\nexport async function getCore(): Promise<typeof import('echarts/core')> {\n if (coreModule) return coreModule\n if (!corePromise) {\n corePromise = import('echarts/core').then((m) => {\n coreModule = m\n return m\n })\n }\n return corePromise\n}\n\n/**\n * Get the cached core module (null if not yet loaded).\n */\nexport function getCoreSync(): typeof import('echarts/core') | null {\n return coreModule\n}\n\n// ─── Module registration ────────────────────────────────────────────────────\n\nconst registered = new Set<string>()\nconst inflight = new Map<string, Promise<void>>()\n\nasync function loadAndRegister(\n core: typeof import('echarts/core'),\n key: string,\n loader: ModuleLoader,\n): Promise<void> {\n if (registered.has(key)) return\n if (inflight.has(key)) return inflight.get(key)\n\n const promise = loader().then((mod) => {\n core.use(mod as any)\n registered.add(key)\n inflight.delete(key)\n })\n inflight.set(key, promise)\n return promise\n}\n\n/**\n * Analyze an ECharts option object and dynamically import only the\n * required chart types, components, and renderer. All imports are\n * cached — subsequent calls with the same types are instant.\n */\nexport async function ensureModules(\n option: LooseOption,\n renderer: 'canvas' | 'svg' = 'canvas',\n): Promise<typeof import('echarts/core')> {\n const core = await getCore()\n const loads: Promise<void>[] = []\n\n // Renderer (always needed)\n loads.push(\n loadAndRegister(core, `renderer:${renderer}`, RENDERERS[renderer]!),\n )\n\n // Normalize series to array for analysis\n const rawSeries = option.series\n const seriesList: Record<string, unknown>[] = rawSeries\n ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<\n string,\n unknown\n >[])\n : []\n\n // Chart types from series[].type\n for (const s of seriesList) {\n const type = s.type as string | undefined\n if (type && CHARTS[type]) {\n loads.push(loadAndRegister(core, `chart:${type}`, CHARTS[type]!))\n }\n }\n\n // Components from top-level config keys\n for (const key of Object.keys(option)) {\n if (COMPONENTS[key]) {\n loads.push(loadAndRegister(core, `component:${key}`, COMPONENTS[key]!))\n }\n }\n\n // Series-level features (markPoint, markLine, markArea)\n for (const s of seriesList) {\n for (const key of Object.keys(s)) {\n if (SERIES_FEATURES[key]) {\n loads.push(\n loadAndRegister(core, `feature:${key}`, SERIES_FEATURES[key]!),\n )\n }\n }\n }\n\n await Promise.all(loads)\n return core\n}\n\n/**\n * Manually register ECharts modules (for tree-shaking entry point).\n * Call this at app startup instead of relying on auto-detection.\n *\n * @example\n * ```ts\n * import { use } from '@pyreon/charts/manual'\n * import { BarChart } from 'echarts/charts'\n * import { GridComponent, TooltipComponent } from 'echarts/components'\n * import { CanvasRenderer } from 'echarts/renderers'\n *\n * use(BarChart, GridComponent, TooltipComponent, CanvasRenderer)\n * ```\n */\nexport function manualUse(...modules: unknown[]): void {\n const core = getCoreSync()\n if (core) {\n core.use(modules as any)\n } else {\n // Core not loaded yet — queue for when it loads\n getCore().then((c) => c.use(modules as any))\n }\n}\n\n// ─── Reset (for testing) ────────────────────────────────────────────────────\n\nexport function _resetLoader(): void {\n registered.clear()\n inflight.clear()\n coreModule = null\n corePromise = null\n}\n","import { onUnmount } from '@pyreon/core'\nimport { effect, signal } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport { ensureModules } from './loader'\nimport type { UseChartConfig, UseChartResult } from './types'\n\n/**\n * Reactive ECharts hook. Creates a chart instance bound to a container\n * element, with automatic module lazy-loading, signal tracking, resize\n * handling, error capture, and cleanup.\n *\n * Generic parameter `TOption` narrows the option type for exact autocomplete.\n * Use `ComposeOption<SeriesUnion>` from ECharts to restrict to specific chart types.\n *\n * @example\n * ```tsx\n * // Default — accepts any ECharts option\n * const chart = useChart(() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * }))\n *\n * // Strict — only bar + line allowed, full autocomplete\n * import type { ComposeOption, BarSeriesOption, LineSeriesOption } from '@pyreon/charts'\n * type MyChartOption = ComposeOption<BarSeriesOption | LineSeriesOption>\n *\n * const chart = useChart<MyChartOption>(() => ({\n * series: [{ type: 'bar', data: revenue() }], // ✓\n * }))\n * ```\n */\nexport function useChart<TOption extends EChartsOption = EChartsOption>(\n optionsFn: () => TOption,\n config?: UseChartConfig,\n): UseChartResult {\n const instance = signal<import('echarts/core').ECharts | null>(null)\n const loading = signal(true)\n const error = signal<Error | null>(null)\n const container = signal<HTMLElement | null>(null)\n const renderer = config?.renderer ?? 'canvas'\n\n let observer: ResizeObserver | null = null\n let initialized = false\n\n // Initialize chart when container is bound\n effect(() => {\n const el = container()\n if (!el || initialized) return\n\n initialized = true\n\n let opts: EChartsOption\n try {\n opts = optionsFn()\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n return\n }\n\n // Load required ECharts modules, then create chart\n ensureModules(opts as Record<string, unknown>, renderer)\n .then((core) => {\n // Guard: component may have unmounted during async load\n if (!container.peek()) return\n\n try {\n const chart = core.init(el, config?.theme as any, {\n renderer,\n locale: config?.locale,\n devicePixelRatio: config?.devicePixelRatio,\n width: config?.width,\n height: config?.height,\n })\n\n chart.setOption(opts)\n instance.set(chart)\n loading.set(false)\n error.set(null)\n\n config?.onInit?.(chart)\n\n // ResizeObserver for auto-resize\n observer = new ResizeObserver(() => {\n chart.resize()\n })\n observer.observe(el)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n }\n })\n .catch((err) => {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n })\n })\n\n // Reactive updates — re-run when signals in optionsFn change\n effect(() => {\n const chart = instance()\n if (!chart) return\n\n try {\n const opts = optionsFn()\n chart.setOption(opts, {\n notMerge: config?.notMerge ?? false,\n lazyUpdate: config?.lazyUpdate ?? true,\n })\n error.set(null)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n }\n })\n\n // Cleanup on unmount\n onUnmount(() => {\n observer?.disconnect()\n observer = null\n\n const chart = instance.peek()\n if (chart) {\n chart.dispose()\n instance.set(null)\n }\n\n initialized = false\n })\n\n return {\n ref: (el: Element | null) => container.set(el as HTMLElement | null),\n instance,\n loading,\n error,\n resize: () => instance.peek()?.resize(),\n }\n}\n","//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport { effect } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport type { ChartProps } from './types'\nimport { useChart } from './use-chart'\n\n/**\n * Reactive chart component. Wraps useChart in a div with automatic\n * event binding.\n *\n * @example\n * ```tsx\n * // Default — any chart type\n * <Chart\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * tooltip: {},\n * })}\n * style=\"height: 400px\"\n * />\n *\n * // Strict — only specific chart types\n * import type { ComposeOption, BarSeriesOption } from '@pyreon/charts'\n * <Chart<ComposeOption<BarSeriesOption>>\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * })}\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function Chart<TOption extends EChartsOption = EChartsOption>(\n props: ChartProps<TOption>,\n): VNodeChild {\n const chart = useChart(props.options, {\n theme: props.theme,\n renderer: props.renderer,\n })\n\n // Bind events when instance is ready\n effect(() => {\n const inst = chart.instance()\n if (!inst) return\n\n // Handlers are duck-typed ChartEventParams — cast needed because\n // echarts/core and echarts export incompatible private class types\n if (props.onClick) inst.on('click', props.onClick as any)\n if (props.onMouseover) inst.on('mouseover', props.onMouseover as any)\n if (props.onMouseout) inst.on('mouseout', props.onMouseout as any)\n })\n\n return () => <div ref={chart.ref} style={props.style} class={props.class} />\n}\n"],"x_google_ignoreList":[2],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/loader.ts","../src/use-chart.ts","../../../node_modules/.bun/@pyreon+core@0.7.3/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/chart-component.tsx"],"sourcesContent":["/**\n * Lazy loading and auto-detection for ECharts modules.\n *\n * Maps config keys to ECharts modular imports. Only loads what's needed,\n * caches after first load. The echarts/core module itself is lazy-loaded\n * on first use — zero ECharts bytes until a chart actually renders.\n */\n\n/**\n * Loose option type for internal module analysis.\n * The strict EChartsOption type is used at the consumer-facing API level.\n */\ntype LooseOption = Record<string, unknown> & {\n series?: unknown\n}\n\ntype ModuleLoader = () => Promise<unknown>\n\n// ─── Chart type mapping ─────────────────────────────────────────────────────\n\nconst CHARTS: Record<string, ModuleLoader> = {\n bar: () => import('echarts/charts').then((m) => m.BarChart),\n line: () => import('echarts/charts').then((m) => m.LineChart),\n pie: () => import('echarts/charts').then((m) => m.PieChart),\n scatter: () => import('echarts/charts').then((m) => m.ScatterChart),\n radar: () => import('echarts/charts').then((m) => m.RadarChart),\n heatmap: () => import('echarts/charts').then((m) => m.HeatmapChart),\n treemap: () => import('echarts/charts').then((m) => m.TreemapChart),\n sunburst: () => import('echarts/charts').then((m) => m.SunburstChart),\n sankey: () => import('echarts/charts').then((m) => m.SankeyChart),\n funnel: () => import('echarts/charts').then((m) => m.FunnelChart),\n gauge: () => import('echarts/charts').then((m) => m.GaugeChart),\n graph: () => import('echarts/charts').then((m) => m.GraphChart),\n tree: () => import('echarts/charts').then((m) => m.TreeChart),\n boxplot: () => import('echarts/charts').then((m) => m.BoxplotChart),\n candlestick: () => import('echarts/charts').then((m) => m.CandlestickChart),\n parallel: () => import('echarts/charts').then((m) => m.ParallelChart),\n themeRiver: () => import('echarts/charts').then((m) => m.ThemeRiverChart),\n effectScatter: () =>\n import('echarts/charts').then((m) => m.EffectScatterChart),\n lines: () => import('echarts/charts').then((m) => m.LinesChart),\n pictorialBar: () => import('echarts/charts').then((m) => m.PictorialBarChart),\n custom: () => import('echarts/charts').then((m) => m.CustomChart),\n map: () => import('echarts/charts').then((m) => m.MapChart),\n}\n\n// ─── Component mapping ──────────────────────────────────────────────────────\n\n// Multiple config keys can map to the same component (xAxis/yAxis → Grid)\nconst COMPONENTS: Record<string, ModuleLoader> = {\n grid: () => import('echarts/components').then((m) => m.GridComponent),\n xAxis: () => import('echarts/components').then((m) => m.GridComponent),\n yAxis: () => import('echarts/components').then((m) => m.GridComponent),\n polar: () => import('echarts/components').then((m) => m.PolarComponent),\n radar: () => import('echarts/components').then((m) => m.RadarComponent),\n geo: () => import('echarts/components').then((m) => m.GeoComponent),\n tooltip: () => import('echarts/components').then((m) => m.TooltipComponent),\n legend: () => import('echarts/components').then((m) => m.LegendComponent),\n toolbox: () => import('echarts/components').then((m) => m.ToolboxComponent),\n title: () => import('echarts/components').then((m) => m.TitleComponent),\n dataZoom: () => import('echarts/components').then((m) => m.DataZoomComponent),\n visualMap: () =>\n import('echarts/components').then((m) => m.VisualMapComponent),\n timeline: () => import('echarts/components').then((m) => m.TimelineComponent),\n graphic: () => import('echarts/components').then((m) => m.GraphicComponent),\n brush: () => import('echarts/components').then((m) => m.BrushComponent),\n calendar: () => import('echarts/components').then((m) => m.CalendarComponent),\n dataset: () => import('echarts/components').then((m) => m.DatasetComponent),\n aria: () => import('echarts/components').then((m) => m.AriaComponent),\n}\n\n// Series-level features\nconst SERIES_FEATURES: Record<string, ModuleLoader> = {\n markPoint: () =>\n import('echarts/components').then((m) => m.MarkPointComponent),\n markLine: () => import('echarts/components').then((m) => m.MarkLineComponent),\n markArea: () => import('echarts/components').then((m) => m.MarkAreaComponent),\n}\n\n// ─── Renderers ──────────────────────────────────────────────────────────────\n\nconst RENDERERS: Record<string, ModuleLoader> = {\n canvas: () => import('echarts/renderers').then((m) => m.CanvasRenderer),\n svg: () => import('echarts/renderers').then((m) => m.SVGRenderer),\n}\n\n// ─── Core loading ───────────────────────────────────────────────────────────\n\nlet coreModule: typeof import('echarts/core') | null = null\nlet corePromise: Promise<typeof import('echarts/core')> | null = null\n\n/**\n * Lazily load echarts/core. Cached after first call.\n */\nexport async function getCore(): Promise<typeof import('echarts/core')> {\n if (coreModule) return coreModule\n if (!corePromise) {\n corePromise = import('echarts/core').then((m) => {\n coreModule = m\n return m\n })\n }\n return corePromise\n}\n\n/**\n * Get the cached core module (null if not yet loaded).\n */\nexport function getCoreSync(): typeof import('echarts/core') | null {\n return coreModule\n}\n\n// ─── Module registration ────────────────────────────────────────────────────\n\nconst registered = new Set<string>()\nconst inflight = new Map<string, Promise<void>>()\n\nasync function loadAndRegister(\n core: typeof import('echarts/core'),\n key: string,\n loader: ModuleLoader,\n): Promise<void> {\n if (registered.has(key)) return\n if (inflight.has(key)) return inflight.get(key)\n\n const promise = loader().then((mod) => {\n core.use(mod as any)\n registered.add(key)\n inflight.delete(key)\n })\n inflight.set(key, promise)\n return promise\n}\n\n/**\n * Analyze an ECharts option object and dynamically import only the\n * required chart types, components, and renderer. All imports are\n * cached — subsequent calls with the same types are instant.\n */\nexport async function ensureModules(\n option: LooseOption,\n renderer: 'canvas' | 'svg' = 'canvas',\n): Promise<typeof import('echarts/core')> {\n const core = await getCore()\n const loads: Promise<void>[] = []\n\n // Renderer (always needed)\n loads.push(\n loadAndRegister(core, `renderer:${renderer}`, RENDERERS[renderer]!),\n )\n\n // Normalize series to array for analysis\n const rawSeries = option.series\n const seriesList: Record<string, unknown>[] = rawSeries\n ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<\n string,\n unknown\n >[])\n : []\n\n // Chart types from series[].type\n for (const s of seriesList) {\n const type = s.type as string | undefined\n if (type && CHARTS[type]) {\n loads.push(loadAndRegister(core, `chart:${type}`, CHARTS[type]!))\n }\n }\n\n // Components from top-level config keys\n for (const key of Object.keys(option)) {\n if (COMPONENTS[key]) {\n loads.push(loadAndRegister(core, `component:${key}`, COMPONENTS[key]!))\n }\n }\n\n // Series-level features (markPoint, markLine, markArea)\n for (const s of seriesList) {\n for (const key of Object.keys(s)) {\n if (SERIES_FEATURES[key]) {\n loads.push(\n loadAndRegister(core, `feature:${key}`, SERIES_FEATURES[key]!),\n )\n }\n }\n }\n\n await Promise.all(loads)\n return core\n}\n\n/**\n * Manually register ECharts modules (for tree-shaking entry point).\n * Call this at app startup instead of relying on auto-detection.\n *\n * @example\n * ```ts\n * import { use } from '@pyreon/charts/manual'\n * import { BarChart } from 'echarts/charts'\n * import { GridComponent, TooltipComponent } from 'echarts/components'\n * import { CanvasRenderer } from 'echarts/renderers'\n *\n * use(BarChart, GridComponent, TooltipComponent, CanvasRenderer)\n * ```\n */\nexport function manualUse(...modules: unknown[]): void {\n const core = getCoreSync()\n if (core) {\n core.use(modules as any)\n } else {\n // Core not loaded yet — queue for when it loads\n getCore().then((c) => c.use(modules as any))\n }\n}\n\n// ─── Reset (for testing) ────────────────────────────────────────────────────\n\nexport function _resetLoader(): void {\n registered.clear()\n inflight.clear()\n coreModule = null\n corePromise = null\n}\n","import { onUnmount } from '@pyreon/core'\nimport { effect, signal } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport { ensureModules } from './loader'\nimport type { UseChartConfig, UseChartResult } from './types'\n\n/**\n * Reactive ECharts hook. Creates a chart instance bound to a container\n * element, with automatic module lazy-loading, signal tracking, resize\n * handling, error capture, and cleanup.\n *\n * Generic parameter `TOption` narrows the option type for exact autocomplete.\n * Use `ComposeOption<SeriesUnion>` from ECharts to restrict to specific chart types.\n *\n * @example\n * ```tsx\n * // Default — accepts any ECharts option\n * const chart = useChart(() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * }))\n *\n * // Strict — only bar + line allowed, full autocomplete\n * import type { ComposeOption, BarSeriesOption, LineSeriesOption } from '@pyreon/charts'\n * type MyChartOption = ComposeOption<BarSeriesOption | LineSeriesOption>\n *\n * const chart = useChart<MyChartOption>(() => ({\n * series: [{ type: 'bar', data: revenue() }], // ✓\n * }))\n * ```\n */\nexport function useChart<TOption extends EChartsOption = EChartsOption>(\n optionsFn: () => TOption,\n config?: UseChartConfig,\n): UseChartResult {\n const instance = signal<import('echarts/core').ECharts | null>(null)\n const loading = signal(true)\n const error = signal<Error | null>(null)\n const container = signal<HTMLElement | null>(null)\n const renderer = config?.renderer ?? 'canvas'\n\n let observer: ResizeObserver | null = null\n let initialized = false\n\n // Initialize chart when container is bound\n effect(() => {\n const el = container()\n if (!el || initialized) return\n\n initialized = true\n\n let opts: EChartsOption\n try {\n opts = optionsFn()\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n return\n }\n\n // Load required ECharts modules, then create chart\n ensureModules(opts as Record<string, unknown>, renderer)\n .then((core) => {\n // Guard: component may have unmounted during async load\n if (!container.peek()) return\n\n try {\n const chart = core.init(el, config?.theme as any, {\n renderer,\n ...(config?.locale != null ? { locale: config.locale } : {}),\n ...(config?.devicePixelRatio != null\n ? { devicePixelRatio: config.devicePixelRatio }\n : {}),\n ...(config?.width != null ? { width: config.width } : {}),\n ...(config?.height != null ? { height: config.height } : {}),\n })\n\n chart.setOption(opts)\n instance.set(chart)\n loading.set(false)\n error.set(null)\n\n config?.onInit?.(chart)\n\n // ResizeObserver for auto-resize\n observer = new ResizeObserver(() => {\n chart.resize()\n })\n observer.observe(el)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n }\n })\n .catch((err) => {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n })\n })\n\n // Reactive updates — re-run when signals in optionsFn change\n effect(() => {\n const chart = instance()\n if (!chart) return\n\n try {\n const opts = optionsFn()\n chart.setOption(opts, {\n notMerge: config?.notMerge ?? false,\n lazyUpdate: config?.lazyUpdate ?? true,\n })\n error.set(null)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n }\n })\n\n // Cleanup on unmount\n onUnmount(() => {\n observer?.disconnect()\n observer = null\n\n const chart = instance.peek()\n if (chart) {\n chart.dispose()\n instance.set(null)\n }\n\n initialized = false\n })\n\n return {\n ref: (el: Element | null) => container.set(el as HTMLElement | null),\n instance,\n loading,\n error,\n resize: () => instance.peek()?.resize(),\n }\n}\n","//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport { effect } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport type { ChartProps } from './types'\nimport { useChart } from './use-chart'\n\n/**\n * Reactive chart component. Wraps useChart in a div with automatic\n * event binding.\n *\n * @example\n * ```tsx\n * // Default — any chart type\n * <Chart\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * tooltip: {},\n * })}\n * style=\"height: 400px\"\n * />\n *\n * // Strict — only specific chart types\n * import type { ComposeOption, BarSeriesOption } from '@pyreon/charts'\n * <Chart<ComposeOption<BarSeriesOption>>\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * })}\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function Chart<TOption extends EChartsOption = EChartsOption>(\n props: ChartProps<TOption>,\n): VNodeChild {\n const chart = useChart(props.options, {\n ...(props.theme != null ? { theme: props.theme } : {}),\n ...(props.renderer != null ? { renderer: props.renderer } : {}),\n })\n\n // Bind events when instance is ready\n effect(() => {\n const inst = chart.instance()\n if (!inst) return\n\n // Handlers are duck-typed ChartEventParams — cast needed because\n // echarts/core and echarts export incompatible private class types\n if (props.onClick) inst.on('click', props.onClick as any)\n if (props.onMouseover) inst.on('mouseover', props.onMouseover as any)\n if (props.onMouseout) inst.on('mouseout', props.onMouseout as any)\n })\n\n return () => <div ref={chart.ref} style={props.style} class={props.class} />\n}\n"],"x_google_ignoreList":[2],"mappings":"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"}
package/lib/manual.js CHANGED
@@ -178,10 +178,10 @@ function useChart(optionsFn, config) {
178
178
  try {
179
179
  const chart = core.init(el, config?.theme, {
180
180
  renderer,
181
- locale: config?.locale,
182
- devicePixelRatio: config?.devicePixelRatio,
183
- width: config?.width,
184
- height: config?.height
181
+ ...config?.locale != null ? { locale: config.locale } : {},
182
+ ...config?.devicePixelRatio != null ? { devicePixelRatio: config.devicePixelRatio } : {},
183
+ ...config?.width != null ? { width: config.width } : {},
184
+ ...config?.height != null ? { height: config.height } : {}
185
185
  });
186
186
  chart.setOption(opts);
187
187
  instance.set(chart);
@@ -235,7 +235,7 @@ function useChart(optionsFn, config) {
235
235
  }
236
236
 
237
237
  //#endregion
238
- //#region ../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js
238
+ //#region ../../node_modules/.bun/@pyreon+core@0.7.3/node_modules/@pyreon/core/lib/jsx-runtime.js
239
239
  /**
240
240
  * Hyperscript function — the compiled output of JSX.
241
241
  * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
@@ -312,8 +312,8 @@ function jsx(type, props, key) {
312
312
  */
313
313
  function Chart(props) {
314
314
  const chart = useChart(props.options, {
315
- theme: props.theme,
316
- renderer: props.renderer
315
+ ...props.theme != null ? { theme: props.theme } : {},
316
+ ...props.renderer != null ? { renderer: props.renderer } : {}
317
317
  });
318
318
  effect(() => {
319
319
  const inst = chart.instance();
package/lib/manual.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"manual.js","names":[],"sources":["../src/loader.ts","../src/use-chart.ts","../../../node_modules/.bun/@pyreon+core@0.6.0/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/chart-component.tsx"],"sourcesContent":["/**\n * Lazy loading and auto-detection for ECharts modules.\n *\n * Maps config keys to ECharts modular imports. Only loads what's needed,\n * caches after first load. The echarts/core module itself is lazy-loaded\n * on first use — zero ECharts bytes until a chart actually renders.\n */\n\n/**\n * Loose option type for internal module analysis.\n * The strict EChartsOption type is used at the consumer-facing API level.\n */\ntype LooseOption = Record<string, unknown> & {\n series?: unknown\n}\n\ntype ModuleLoader = () => Promise<unknown>\n\n// ─── Chart type mapping ─────────────────────────────────────────────────────\n\nconst CHARTS: Record<string, ModuleLoader> = {\n bar: () => import('echarts/charts').then((m) => m.BarChart),\n line: () => import('echarts/charts').then((m) => m.LineChart),\n pie: () => import('echarts/charts').then((m) => m.PieChart),\n scatter: () => import('echarts/charts').then((m) => m.ScatterChart),\n radar: () => import('echarts/charts').then((m) => m.RadarChart),\n heatmap: () => import('echarts/charts').then((m) => m.HeatmapChart),\n treemap: () => import('echarts/charts').then((m) => m.TreemapChart),\n sunburst: () => import('echarts/charts').then((m) => m.SunburstChart),\n sankey: () => import('echarts/charts').then((m) => m.SankeyChart),\n funnel: () => import('echarts/charts').then((m) => m.FunnelChart),\n gauge: () => import('echarts/charts').then((m) => m.GaugeChart),\n graph: () => import('echarts/charts').then((m) => m.GraphChart),\n tree: () => import('echarts/charts').then((m) => m.TreeChart),\n boxplot: () => import('echarts/charts').then((m) => m.BoxplotChart),\n candlestick: () => import('echarts/charts').then((m) => m.CandlestickChart),\n parallel: () => import('echarts/charts').then((m) => m.ParallelChart),\n themeRiver: () => import('echarts/charts').then((m) => m.ThemeRiverChart),\n effectScatter: () =>\n import('echarts/charts').then((m) => m.EffectScatterChart),\n lines: () => import('echarts/charts').then((m) => m.LinesChart),\n pictorialBar: () => import('echarts/charts').then((m) => m.PictorialBarChart),\n custom: () => import('echarts/charts').then((m) => m.CustomChart),\n map: () => import('echarts/charts').then((m) => m.MapChart),\n}\n\n// ─── Component mapping ──────────────────────────────────────────────────────\n\n// Multiple config keys can map to the same component (xAxis/yAxis → Grid)\nconst COMPONENTS: Record<string, ModuleLoader> = {\n grid: () => import('echarts/components').then((m) => m.GridComponent),\n xAxis: () => import('echarts/components').then((m) => m.GridComponent),\n yAxis: () => import('echarts/components').then((m) => m.GridComponent),\n polar: () => import('echarts/components').then((m) => m.PolarComponent),\n radar: () => import('echarts/components').then((m) => m.RadarComponent),\n geo: () => import('echarts/components').then((m) => m.GeoComponent),\n tooltip: () => import('echarts/components').then((m) => m.TooltipComponent),\n legend: () => import('echarts/components').then((m) => m.LegendComponent),\n toolbox: () => import('echarts/components').then((m) => m.ToolboxComponent),\n title: () => import('echarts/components').then((m) => m.TitleComponent),\n dataZoom: () => import('echarts/components').then((m) => m.DataZoomComponent),\n visualMap: () =>\n import('echarts/components').then((m) => m.VisualMapComponent),\n timeline: () => import('echarts/components').then((m) => m.TimelineComponent),\n graphic: () => import('echarts/components').then((m) => m.GraphicComponent),\n brush: () => import('echarts/components').then((m) => m.BrushComponent),\n calendar: () => import('echarts/components').then((m) => m.CalendarComponent),\n dataset: () => import('echarts/components').then((m) => m.DatasetComponent),\n aria: () => import('echarts/components').then((m) => m.AriaComponent),\n}\n\n// Series-level features\nconst SERIES_FEATURES: Record<string, ModuleLoader> = {\n markPoint: () =>\n import('echarts/components').then((m) => m.MarkPointComponent),\n markLine: () => import('echarts/components').then((m) => m.MarkLineComponent),\n markArea: () => import('echarts/components').then((m) => m.MarkAreaComponent),\n}\n\n// ─── Renderers ──────────────────────────────────────────────────────────────\n\nconst RENDERERS: Record<string, ModuleLoader> = {\n canvas: () => import('echarts/renderers').then((m) => m.CanvasRenderer),\n svg: () => import('echarts/renderers').then((m) => m.SVGRenderer),\n}\n\n// ─── Core loading ───────────────────────────────────────────────────────────\n\nlet coreModule: typeof import('echarts/core') | null = null\nlet corePromise: Promise<typeof import('echarts/core')> | null = null\n\n/**\n * Lazily load echarts/core. Cached after first call.\n */\nexport async function getCore(): Promise<typeof import('echarts/core')> {\n if (coreModule) return coreModule\n if (!corePromise) {\n corePromise = import('echarts/core').then((m) => {\n coreModule = m\n return m\n })\n }\n return corePromise\n}\n\n/**\n * Get the cached core module (null if not yet loaded).\n */\nexport function getCoreSync(): typeof import('echarts/core') | null {\n return coreModule\n}\n\n// ─── Module registration ────────────────────────────────────────────────────\n\nconst registered = new Set<string>()\nconst inflight = new Map<string, Promise<void>>()\n\nasync function loadAndRegister(\n core: typeof import('echarts/core'),\n key: string,\n loader: ModuleLoader,\n): Promise<void> {\n if (registered.has(key)) return\n if (inflight.has(key)) return inflight.get(key)\n\n const promise = loader().then((mod) => {\n core.use(mod as any)\n registered.add(key)\n inflight.delete(key)\n })\n inflight.set(key, promise)\n return promise\n}\n\n/**\n * Analyze an ECharts option object and dynamically import only the\n * required chart types, components, and renderer. All imports are\n * cached — subsequent calls with the same types are instant.\n */\nexport async function ensureModules(\n option: LooseOption,\n renderer: 'canvas' | 'svg' = 'canvas',\n): Promise<typeof import('echarts/core')> {\n const core = await getCore()\n const loads: Promise<void>[] = []\n\n // Renderer (always needed)\n loads.push(\n loadAndRegister(core, `renderer:${renderer}`, RENDERERS[renderer]!),\n )\n\n // Normalize series to array for analysis\n const rawSeries = option.series\n const seriesList: Record<string, unknown>[] = rawSeries\n ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<\n string,\n unknown\n >[])\n : []\n\n // Chart types from series[].type\n for (const s of seriesList) {\n const type = s.type as string | undefined\n if (type && CHARTS[type]) {\n loads.push(loadAndRegister(core, `chart:${type}`, CHARTS[type]!))\n }\n }\n\n // Components from top-level config keys\n for (const key of Object.keys(option)) {\n if (COMPONENTS[key]) {\n loads.push(loadAndRegister(core, `component:${key}`, COMPONENTS[key]!))\n }\n }\n\n // Series-level features (markPoint, markLine, markArea)\n for (const s of seriesList) {\n for (const key of Object.keys(s)) {\n if (SERIES_FEATURES[key]) {\n loads.push(\n loadAndRegister(core, `feature:${key}`, SERIES_FEATURES[key]!),\n )\n }\n }\n }\n\n await Promise.all(loads)\n return core\n}\n\n/**\n * Manually register ECharts modules (for tree-shaking entry point).\n * Call this at app startup instead of relying on auto-detection.\n *\n * @example\n * ```ts\n * import { use } from '@pyreon/charts/manual'\n * import { BarChart } from 'echarts/charts'\n * import { GridComponent, TooltipComponent } from 'echarts/components'\n * import { CanvasRenderer } from 'echarts/renderers'\n *\n * use(BarChart, GridComponent, TooltipComponent, CanvasRenderer)\n * ```\n */\nexport function manualUse(...modules: unknown[]): void {\n const core = getCoreSync()\n if (core) {\n core.use(modules as any)\n } else {\n // Core not loaded yet — queue for when it loads\n getCore().then((c) => c.use(modules as any))\n }\n}\n\n// ─── Reset (for testing) ────────────────────────────────────────────────────\n\nexport function _resetLoader(): void {\n registered.clear()\n inflight.clear()\n coreModule = null\n corePromise = null\n}\n","import { onUnmount } from '@pyreon/core'\nimport { effect, signal } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport { ensureModules } from './loader'\nimport type { UseChartConfig, UseChartResult } from './types'\n\n/**\n * Reactive ECharts hook. Creates a chart instance bound to a container\n * element, with automatic module lazy-loading, signal tracking, resize\n * handling, error capture, and cleanup.\n *\n * Generic parameter `TOption` narrows the option type for exact autocomplete.\n * Use `ComposeOption<SeriesUnion>` from ECharts to restrict to specific chart types.\n *\n * @example\n * ```tsx\n * // Default — accepts any ECharts option\n * const chart = useChart(() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * }))\n *\n * // Strict — only bar + line allowed, full autocomplete\n * import type { ComposeOption, BarSeriesOption, LineSeriesOption } from '@pyreon/charts'\n * type MyChartOption = ComposeOption<BarSeriesOption | LineSeriesOption>\n *\n * const chart = useChart<MyChartOption>(() => ({\n * series: [{ type: 'bar', data: revenue() }], // ✓\n * }))\n * ```\n */\nexport function useChart<TOption extends EChartsOption = EChartsOption>(\n optionsFn: () => TOption,\n config?: UseChartConfig,\n): UseChartResult {\n const instance = signal<import('echarts/core').ECharts | null>(null)\n const loading = signal(true)\n const error = signal<Error | null>(null)\n const container = signal<HTMLElement | null>(null)\n const renderer = config?.renderer ?? 'canvas'\n\n let observer: ResizeObserver | null = null\n let initialized = false\n\n // Initialize chart when container is bound\n effect(() => {\n const el = container()\n if (!el || initialized) return\n\n initialized = true\n\n let opts: EChartsOption\n try {\n opts = optionsFn()\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n return\n }\n\n // Load required ECharts modules, then create chart\n ensureModules(opts as Record<string, unknown>, renderer)\n .then((core) => {\n // Guard: component may have unmounted during async load\n if (!container.peek()) return\n\n try {\n const chart = core.init(el, config?.theme as any, {\n renderer,\n locale: config?.locale,\n devicePixelRatio: config?.devicePixelRatio,\n width: config?.width,\n height: config?.height,\n })\n\n chart.setOption(opts)\n instance.set(chart)\n loading.set(false)\n error.set(null)\n\n config?.onInit?.(chart)\n\n // ResizeObserver for auto-resize\n observer = new ResizeObserver(() => {\n chart.resize()\n })\n observer.observe(el)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n }\n })\n .catch((err) => {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n })\n })\n\n // Reactive updates — re-run when signals in optionsFn change\n effect(() => {\n const chart = instance()\n if (!chart) return\n\n try {\n const opts = optionsFn()\n chart.setOption(opts, {\n notMerge: config?.notMerge ?? false,\n lazyUpdate: config?.lazyUpdate ?? true,\n })\n error.set(null)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n }\n })\n\n // Cleanup on unmount\n onUnmount(() => {\n observer?.disconnect()\n observer = null\n\n const chart = instance.peek()\n if (chart) {\n chart.dispose()\n instance.set(null)\n }\n\n initialized = false\n })\n\n return {\n ref: (el: Element | null) => container.set(el as HTMLElement | null),\n instance,\n loading,\n error,\n resize: () => instance.peek()?.resize(),\n }\n}\n","//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport { effect } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport type { ChartProps } from './types'\nimport { useChart } from './use-chart'\n\n/**\n * Reactive chart component. Wraps useChart in a div with automatic\n * event binding.\n *\n * @example\n * ```tsx\n * // Default — any chart type\n * <Chart\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * tooltip: {},\n * })}\n * style=\"height: 400px\"\n * />\n *\n * // Strict — only specific chart types\n * import type { ComposeOption, BarSeriesOption } from '@pyreon/charts'\n * <Chart<ComposeOption<BarSeriesOption>>\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * })}\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function Chart<TOption extends EChartsOption = EChartsOption>(\n props: ChartProps<TOption>,\n): VNodeChild {\n const chart = useChart(props.options, {\n theme: props.theme,\n renderer: props.renderer,\n })\n\n // Bind events when instance is ready\n effect(() => {\n const inst = chart.instance()\n if (!inst) return\n\n // Handlers are duck-typed ChartEventParams — cast needed because\n // echarts/core and echarts export incompatible private class types\n if (props.onClick) inst.on('click', props.onClick as any)\n if (props.onMouseover) inst.on('mouseover', props.onMouseover as any)\n if (props.onMouseout) inst.on('mouseout', props.onMouseout as any)\n })\n\n return () => <div ref={chart.ref} style={props.style} class={props.class} />\n}\n"],"x_google_ignoreList":[2],"mappings":"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"}
1
+ {"version":3,"file":"manual.js","names":[],"sources":["../src/loader.ts","../src/use-chart.ts","../../../node_modules/.bun/@pyreon+core@0.7.3/node_modules/@pyreon/core/lib/jsx-runtime.js","../src/chart-component.tsx"],"sourcesContent":["/**\n * Lazy loading and auto-detection for ECharts modules.\n *\n * Maps config keys to ECharts modular imports. Only loads what's needed,\n * caches after first load. The echarts/core module itself is lazy-loaded\n * on first use — zero ECharts bytes until a chart actually renders.\n */\n\n/**\n * Loose option type for internal module analysis.\n * The strict EChartsOption type is used at the consumer-facing API level.\n */\ntype LooseOption = Record<string, unknown> & {\n series?: unknown\n}\n\ntype ModuleLoader = () => Promise<unknown>\n\n// ─── Chart type mapping ─────────────────────────────────────────────────────\n\nconst CHARTS: Record<string, ModuleLoader> = {\n bar: () => import('echarts/charts').then((m) => m.BarChart),\n line: () => import('echarts/charts').then((m) => m.LineChart),\n pie: () => import('echarts/charts').then((m) => m.PieChart),\n scatter: () => import('echarts/charts').then((m) => m.ScatterChart),\n radar: () => import('echarts/charts').then((m) => m.RadarChart),\n heatmap: () => import('echarts/charts').then((m) => m.HeatmapChart),\n treemap: () => import('echarts/charts').then((m) => m.TreemapChart),\n sunburst: () => import('echarts/charts').then((m) => m.SunburstChart),\n sankey: () => import('echarts/charts').then((m) => m.SankeyChart),\n funnel: () => import('echarts/charts').then((m) => m.FunnelChart),\n gauge: () => import('echarts/charts').then((m) => m.GaugeChart),\n graph: () => import('echarts/charts').then((m) => m.GraphChart),\n tree: () => import('echarts/charts').then((m) => m.TreeChart),\n boxplot: () => import('echarts/charts').then((m) => m.BoxplotChart),\n candlestick: () => import('echarts/charts').then((m) => m.CandlestickChart),\n parallel: () => import('echarts/charts').then((m) => m.ParallelChart),\n themeRiver: () => import('echarts/charts').then((m) => m.ThemeRiverChart),\n effectScatter: () =>\n import('echarts/charts').then((m) => m.EffectScatterChart),\n lines: () => import('echarts/charts').then((m) => m.LinesChart),\n pictorialBar: () => import('echarts/charts').then((m) => m.PictorialBarChart),\n custom: () => import('echarts/charts').then((m) => m.CustomChart),\n map: () => import('echarts/charts').then((m) => m.MapChart),\n}\n\n// ─── Component mapping ──────────────────────────────────────────────────────\n\n// Multiple config keys can map to the same component (xAxis/yAxis → Grid)\nconst COMPONENTS: Record<string, ModuleLoader> = {\n grid: () => import('echarts/components').then((m) => m.GridComponent),\n xAxis: () => import('echarts/components').then((m) => m.GridComponent),\n yAxis: () => import('echarts/components').then((m) => m.GridComponent),\n polar: () => import('echarts/components').then((m) => m.PolarComponent),\n radar: () => import('echarts/components').then((m) => m.RadarComponent),\n geo: () => import('echarts/components').then((m) => m.GeoComponent),\n tooltip: () => import('echarts/components').then((m) => m.TooltipComponent),\n legend: () => import('echarts/components').then((m) => m.LegendComponent),\n toolbox: () => import('echarts/components').then((m) => m.ToolboxComponent),\n title: () => import('echarts/components').then((m) => m.TitleComponent),\n dataZoom: () => import('echarts/components').then((m) => m.DataZoomComponent),\n visualMap: () =>\n import('echarts/components').then((m) => m.VisualMapComponent),\n timeline: () => import('echarts/components').then((m) => m.TimelineComponent),\n graphic: () => import('echarts/components').then((m) => m.GraphicComponent),\n brush: () => import('echarts/components').then((m) => m.BrushComponent),\n calendar: () => import('echarts/components').then((m) => m.CalendarComponent),\n dataset: () => import('echarts/components').then((m) => m.DatasetComponent),\n aria: () => import('echarts/components').then((m) => m.AriaComponent),\n}\n\n// Series-level features\nconst SERIES_FEATURES: Record<string, ModuleLoader> = {\n markPoint: () =>\n import('echarts/components').then((m) => m.MarkPointComponent),\n markLine: () => import('echarts/components').then((m) => m.MarkLineComponent),\n markArea: () => import('echarts/components').then((m) => m.MarkAreaComponent),\n}\n\n// ─── Renderers ──────────────────────────────────────────────────────────────\n\nconst RENDERERS: Record<string, ModuleLoader> = {\n canvas: () => import('echarts/renderers').then((m) => m.CanvasRenderer),\n svg: () => import('echarts/renderers').then((m) => m.SVGRenderer),\n}\n\n// ─── Core loading ───────────────────────────────────────────────────────────\n\nlet coreModule: typeof import('echarts/core') | null = null\nlet corePromise: Promise<typeof import('echarts/core')> | null = null\n\n/**\n * Lazily load echarts/core. Cached after first call.\n */\nexport async function getCore(): Promise<typeof import('echarts/core')> {\n if (coreModule) return coreModule\n if (!corePromise) {\n corePromise = import('echarts/core').then((m) => {\n coreModule = m\n return m\n })\n }\n return corePromise\n}\n\n/**\n * Get the cached core module (null if not yet loaded).\n */\nexport function getCoreSync(): typeof import('echarts/core') | null {\n return coreModule\n}\n\n// ─── Module registration ────────────────────────────────────────────────────\n\nconst registered = new Set<string>()\nconst inflight = new Map<string, Promise<void>>()\n\nasync function loadAndRegister(\n core: typeof import('echarts/core'),\n key: string,\n loader: ModuleLoader,\n): Promise<void> {\n if (registered.has(key)) return\n if (inflight.has(key)) return inflight.get(key)\n\n const promise = loader().then((mod) => {\n core.use(mod as any)\n registered.add(key)\n inflight.delete(key)\n })\n inflight.set(key, promise)\n return promise\n}\n\n/**\n * Analyze an ECharts option object and dynamically import only the\n * required chart types, components, and renderer. All imports are\n * cached — subsequent calls with the same types are instant.\n */\nexport async function ensureModules(\n option: LooseOption,\n renderer: 'canvas' | 'svg' = 'canvas',\n): Promise<typeof import('echarts/core')> {\n const core = await getCore()\n const loads: Promise<void>[] = []\n\n // Renderer (always needed)\n loads.push(\n loadAndRegister(core, `renderer:${renderer}`, RENDERERS[renderer]!),\n )\n\n // Normalize series to array for analysis\n const rawSeries = option.series\n const seriesList: Record<string, unknown>[] = rawSeries\n ? ((Array.isArray(rawSeries) ? rawSeries : [rawSeries]) as Record<\n string,\n unknown\n >[])\n : []\n\n // Chart types from series[].type\n for (const s of seriesList) {\n const type = s.type as string | undefined\n if (type && CHARTS[type]) {\n loads.push(loadAndRegister(core, `chart:${type}`, CHARTS[type]!))\n }\n }\n\n // Components from top-level config keys\n for (const key of Object.keys(option)) {\n if (COMPONENTS[key]) {\n loads.push(loadAndRegister(core, `component:${key}`, COMPONENTS[key]!))\n }\n }\n\n // Series-level features (markPoint, markLine, markArea)\n for (const s of seriesList) {\n for (const key of Object.keys(s)) {\n if (SERIES_FEATURES[key]) {\n loads.push(\n loadAndRegister(core, `feature:${key}`, SERIES_FEATURES[key]!),\n )\n }\n }\n }\n\n await Promise.all(loads)\n return core\n}\n\n/**\n * Manually register ECharts modules (for tree-shaking entry point).\n * Call this at app startup instead of relying on auto-detection.\n *\n * @example\n * ```ts\n * import { use } from '@pyreon/charts/manual'\n * import { BarChart } from 'echarts/charts'\n * import { GridComponent, TooltipComponent } from 'echarts/components'\n * import { CanvasRenderer } from 'echarts/renderers'\n *\n * use(BarChart, GridComponent, TooltipComponent, CanvasRenderer)\n * ```\n */\nexport function manualUse(...modules: unknown[]): void {\n const core = getCoreSync()\n if (core) {\n core.use(modules as any)\n } else {\n // Core not loaded yet — queue for when it loads\n getCore().then((c) => c.use(modules as any))\n }\n}\n\n// ─── Reset (for testing) ────────────────────────────────────────────────────\n\nexport function _resetLoader(): void {\n registered.clear()\n inflight.clear()\n coreModule = null\n corePromise = null\n}\n","import { onUnmount } from '@pyreon/core'\nimport { effect, signal } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport { ensureModules } from './loader'\nimport type { UseChartConfig, UseChartResult } from './types'\n\n/**\n * Reactive ECharts hook. Creates a chart instance bound to a container\n * element, with automatic module lazy-loading, signal tracking, resize\n * handling, error capture, and cleanup.\n *\n * Generic parameter `TOption` narrows the option type for exact autocomplete.\n * Use `ComposeOption<SeriesUnion>` from ECharts to restrict to specific chart types.\n *\n * @example\n * ```tsx\n * // Default — accepts any ECharts option\n * const chart = useChart(() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * }))\n *\n * // Strict — only bar + line allowed, full autocomplete\n * import type { ComposeOption, BarSeriesOption, LineSeriesOption } from '@pyreon/charts'\n * type MyChartOption = ComposeOption<BarSeriesOption | LineSeriesOption>\n *\n * const chart = useChart<MyChartOption>(() => ({\n * series: [{ type: 'bar', data: revenue() }], // ✓\n * }))\n * ```\n */\nexport function useChart<TOption extends EChartsOption = EChartsOption>(\n optionsFn: () => TOption,\n config?: UseChartConfig,\n): UseChartResult {\n const instance = signal<import('echarts/core').ECharts | null>(null)\n const loading = signal(true)\n const error = signal<Error | null>(null)\n const container = signal<HTMLElement | null>(null)\n const renderer = config?.renderer ?? 'canvas'\n\n let observer: ResizeObserver | null = null\n let initialized = false\n\n // Initialize chart when container is bound\n effect(() => {\n const el = container()\n if (!el || initialized) return\n\n initialized = true\n\n let opts: EChartsOption\n try {\n opts = optionsFn()\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n return\n }\n\n // Load required ECharts modules, then create chart\n ensureModules(opts as Record<string, unknown>, renderer)\n .then((core) => {\n // Guard: component may have unmounted during async load\n if (!container.peek()) return\n\n try {\n const chart = core.init(el, config?.theme as any, {\n renderer,\n ...(config?.locale != null ? { locale: config.locale } : {}),\n ...(config?.devicePixelRatio != null\n ? { devicePixelRatio: config.devicePixelRatio }\n : {}),\n ...(config?.width != null ? { width: config.width } : {}),\n ...(config?.height != null ? { height: config.height } : {}),\n })\n\n chart.setOption(opts)\n instance.set(chart)\n loading.set(false)\n error.set(null)\n\n config?.onInit?.(chart)\n\n // ResizeObserver for auto-resize\n observer = new ResizeObserver(() => {\n chart.resize()\n })\n observer.observe(el)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n }\n })\n .catch((err) => {\n error.set(err instanceof Error ? err : new Error(String(err)))\n loading.set(false)\n })\n })\n\n // Reactive updates — re-run when signals in optionsFn change\n effect(() => {\n const chart = instance()\n if (!chart) return\n\n try {\n const opts = optionsFn()\n chart.setOption(opts, {\n notMerge: config?.notMerge ?? false,\n lazyUpdate: config?.lazyUpdate ?? true,\n })\n error.set(null)\n } catch (err) {\n error.set(err instanceof Error ? err : new Error(String(err)))\n }\n })\n\n // Cleanup on unmount\n onUnmount(() => {\n observer?.disconnect()\n observer = null\n\n const chart = instance.peek()\n if (chart) {\n chart.dispose()\n instance.set(null)\n }\n\n initialized = false\n })\n\n return {\n ref: (el: Element | null) => container.set(el as HTMLElement | null),\n instance,\n loading,\n error,\n resize: () => instance.peek()?.resize(),\n }\n}\n","//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport { effect } from '@pyreon/reactivity'\nimport type { EChartsOption } from 'echarts'\nimport type { ChartProps } from './types'\nimport { useChart } from './use-chart'\n\n/**\n * Reactive chart component. Wraps useChart in a div with automatic\n * event binding.\n *\n * @example\n * ```tsx\n * // Default — any chart type\n * <Chart\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * tooltip: {},\n * })}\n * style=\"height: 400px\"\n * />\n *\n * // Strict — only specific chart types\n * import type { ComposeOption, BarSeriesOption } from '@pyreon/charts'\n * <Chart<ComposeOption<BarSeriesOption>>\n * options={() => ({\n * series: [{ type: 'bar', data: revenue() }],\n * })}\n * style=\"height: 400px\"\n * />\n * ```\n */\nexport function Chart<TOption extends EChartsOption = EChartsOption>(\n props: ChartProps<TOption>,\n): VNodeChild {\n const chart = useChart(props.options, {\n ...(props.theme != null ? { theme: props.theme } : {}),\n ...(props.renderer != null ? { renderer: props.renderer } : {}),\n })\n\n // Bind events when instance is ready\n effect(() => {\n const inst = chart.instance()\n if (!inst) return\n\n // Handlers are duck-typed ChartEventParams — cast needed because\n // echarts/core and echarts export incompatible private class types\n if (props.onClick) inst.on('click', props.onClick as any)\n if (props.onMouseover) inst.on('mouseover', props.onMouseover as any)\n if (props.onMouseout) inst.on('mouseout', props.onMouseout as any)\n })\n\n return () => <div ref={chart.ref} style={props.style} class={props.class} />\n}\n"],"x_google_ignoreList":[2],"mappings":"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"}