import { effect, signal } from "@pyreon/reactivity";
import { onUnmount } from "@pyreon/core";

//#region src/loader.ts
const CHARTS = {
	bar: () => import("./charts-lo2KeDld.js").then((m) => m.BarChart),
	line: () => import("./charts-lo2KeDld.js").then((m) => m.LineChart),
	pie: () => import("./charts-lo2KeDld.js").then((m) => m.PieChart),
	scatter: () => import("./charts-lo2KeDld.js").then((m) => m.ScatterChart),
	radar: () => import("./charts-lo2KeDld.js").then((m) => m.RadarChart),
	heatmap: () => import("./charts-lo2KeDld.js").then((m) => m.HeatmapChart),
	treemap: () => import("./charts-lo2KeDld.js").then((m) => m.TreemapChart),
	sunburst: () => import("./charts-lo2KeDld.js").then((m) => m.SunburstChart),
	sankey: () => import("./charts-lo2KeDld.js").then((m) => m.SankeyChart),
	funnel: () => import("./charts-lo2KeDld.js").then((m) => m.FunnelChart),
	gauge: () => import("./charts-lo2KeDld.js").then((m) => m.GaugeChart),
	graph: () => import("./charts-lo2KeDld.js").then((m) => m.GraphChart),
	tree: () => import("./charts-lo2KeDld.js").then((m) => m.TreeChart),
	boxplot: () => import("./charts-lo2KeDld.js").then((m) => m.BoxplotChart),
	candlestick: () => import("./charts-lo2KeDld.js").then((m) => m.CandlestickChart),
	parallel: () => import("./charts-lo2KeDld.js").then((m) => m.ParallelChart),
	themeRiver: () => import("./charts-lo2KeDld.js").then((m) => m.ThemeRiverChart),
	effectScatter: () => import("./charts-lo2KeDld.js").then((m) => m.EffectScatterChart),
	lines: () => import("./charts-lo2KeDld.js").then((m) => m.LinesChart),
	pictorialBar: () => import("./charts-lo2KeDld.js").then((m) => m.PictorialBarChart),
	custom: () => import("./charts-lo2KeDld.js").then((m) => m.CustomChart),
	map: () => import("./charts-lo2KeDld.js").then((m) => m.MapChart)
};
const COMPONENTS = {
	grid: () => import("./components-ClWy1Ztp.js").then((m) => m.GridComponent),
	xAxis: () => import("./components-ClWy1Ztp.js").then((m) => m.GridComponent),
	yAxis: () => import("./components-ClWy1Ztp.js").then((m) => m.GridComponent),
	polar: () => import("./components-ClWy1Ztp.js").then((m) => m.PolarComponent),
	radar: () => import("./components-ClWy1Ztp.js").then((m) => m.RadarComponent),
	geo: () => import("./components-ClWy1Ztp.js").then((m) => m.GeoComponent),
	tooltip: () => import("./components-ClWy1Ztp.js").then((m) => m.TooltipComponent),
	legend: () => import("./components-ClWy1Ztp.js").then((m) => m.LegendComponent),
	toolbox: () => import("./components-ClWy1Ztp.js").then((m) => m.ToolboxComponent),
	title: () => import("./components-ClWy1Ztp.js").then((m) => m.TitleComponent),
	dataZoom: () => import("./components-ClWy1Ztp.js").then((m) => m.DataZoomComponent),
	visualMap: () => import("./components-ClWy1Ztp.js").then((m) => m.VisualMapComponent),
	timeline: () => import("./components-ClWy1Ztp.js").then((m) => m.TimelineComponent),
	graphic: () => import("./components-ClWy1Ztp.js").then((m) => m.GraphicComponent),
	brush: () => import("./components-ClWy1Ztp.js").then((m) => m.BrushComponent),
	calendar: () => import("./components-ClWy1Ztp.js").then((m) => m.CalendarComponent),
	dataset: () => import("./components-ClWy1Ztp.js").then((m) => m.DatasetComponent),
	aria: () => import("./components-ClWy1Ztp.js").then((m) => m.AriaComponent)
};
const SERIES_FEATURES = {
	markPoint: () => import("./components-ClWy1Ztp.js").then((m) => m.MarkPointComponent),
	markLine: () => import("./components-ClWy1Ztp.js").then((m) => m.MarkLineComponent),
	markArea: () => import("./components-ClWy1Ztp.js").then((m) => m.MarkAreaComponent)
};
const RENDERERS = {
	canvas: () => import("./renderers-BnAAXHfG.js").then((m) => m.CanvasRenderer),
	svg: () => import("./renderers-BnAAXHfG.js").then((m) => m.SVGRenderer)
};
let coreModule = null;
let corePromise = null;
/**
* Lazily load echarts/core. Cached after first call.
*/
async function getCore() {
	if (coreModule) return coreModule;
	if (!corePromise) corePromise = import("./core-BiuQ3y-t.js").then((m) => {
		coreModule = m;
		return m;
	});
	return corePromise;
}
const registered = /* @__PURE__ */ new Set();
const inflight = /* @__PURE__ */ new Map();
async function loadAndRegister(core, key, loader) {
	if (registered.has(key)) return;
	if (inflight.has(key)) return inflight.get(key);
	const promise = loader().then((mod) => {
		core.use(mod);
		registered.add(key);
		inflight.delete(key);
	});
	inflight.set(key, promise);
	return promise;
}
/**
* Analyze an ECharts option object and dynamically import only the
* required chart types, components, and renderer. All imports are
* cached — subsequent calls with the same types are instant.
*/
async function ensureModules(option, renderer = "canvas") {
	const core = await getCore();
	const loads = [];
	const rendererLoader = RENDERERS[renderer];
	if (rendererLoader) loads.push(loadAndRegister(core, `renderer:${renderer}`, rendererLoader));
	const rawSeries = option.series;
	const seriesList = rawSeries ? Array.isArray(rawSeries) ? rawSeries : [rawSeries] : [];
	for (const s of seriesList) {
		const type = s.type;
		const chartLoader = type ? CHARTS[type] : void 0;
		if (chartLoader) loads.push(loadAndRegister(core, `chart:${type}`, chartLoader));
	}
	for (const key of Object.keys(option)) {
		const compLoader = COMPONENTS[key];
		if (compLoader) loads.push(loadAndRegister(core, `component:${key}`, compLoader));
	}
	for (const s of seriesList) for (const key of Object.keys(s)) {
		const featureLoader = SERIES_FEATURES[key];
		if (featureLoader) loads.push(loadAndRegister(core, `feature:${key}`, featureLoader));
	}
	await Promise.all(loads);
	return core;
}

//#endregion
//#region src/use-chart.ts
/**
* Reactive ECharts hook. Creates a chart instance bound to a container
* element, with automatic module lazy-loading, signal tracking, resize
* handling, error capture, and cleanup.
*
* Generic parameter `TOption` narrows the option type for exact autocomplete.
* Use `ComposeOption<SeriesUnion>` from ECharts to restrict to specific chart types.
*
* @example
* ```tsx
* // Default — accepts any ECharts option
* const chart = useChart(() => ({
*   series: [{ type: 'bar', data: revenue() }],
* }))
*
* // Strict — only bar + line allowed, full autocomplete
* import type { ComposeOption, BarSeriesOption, LineSeriesOption } from '@pyreon/charts'
* type MyChartOption = ComposeOption<BarSeriesOption | LineSeriesOption>
*
* const chart = useChart<MyChartOption>(() => ({
*   series: [{ type: 'bar', data: revenue() }],  // ✓
* }))
* ```
*/
function useChart(optionsFn, config) {
	const instance = signal(null);
	const loading = signal(true);
	const error = signal(null);
	const container = signal(null);
	const renderer = config?.renderer ?? "canvas";
	let observer = null;
	let initialized = false;
	effect(() => {
		const el = container();
		if (!el || initialized) return;
		initialized = true;
		let opts;
		try {
			opts = optionsFn();
		} catch (err) {
			error.set(err instanceof Error ? err : new Error(String(err)));
			loading.set(false);
			return;
		}
		ensureModules(opts, renderer).then((core) => {
			if (!container.peek()) return;
			try {
				const chart = core.init(el, config?.theme ?? null, {
					renderer,
					...config?.locale != null ? { locale: config.locale } : {},
					...config?.devicePixelRatio != null ? { devicePixelRatio: config.devicePixelRatio } : {},
					...config?.width != null ? { width: config.width } : {},
					...config?.height != null ? { height: config.height } : {}
				});
				chart.setOption(opts);
				instance.set(chart);
				loading.set(false);
				error.set(null);
				config?.onInit?.(chart);
				observer = new ResizeObserver(() => {
					chart.resize();
				});
				observer.observe(el);
			} catch (err) {
				error.set(err instanceof Error ? err : new Error(String(err)));
				loading.set(false);
			}
		}).catch((err) => {
			error.set(err instanceof Error ? err : new Error(String(err)));
			loading.set(false);
		});
	});
	effect(() => {
		const chart = instance();
		if (!chart) return;
		try {
			const opts = optionsFn();
			chart.setOption(opts, {
				notMerge: config?.notMerge ?? false,
				lazyUpdate: config?.lazyUpdate ?? true
			});
			error.set(null);
		} catch (err) {
			error.set(err instanceof Error ? err : new Error(String(err)));
		}
	});
	onUnmount(() => {
		observer?.disconnect();
		observer = null;
		const chart = instance.peek();
		if (chart) {
			chart.dispose();
			instance.set(null);
		}
		initialized = false;
	});
	return {
		ref: (el) => container.set(el),
		instance,
		loading,
		error,
		resize: () => instance.peek()?.resize()
	};
}

//#endregion
//#region ../../core/core/lib/jsx-runtime.js
/**
* Hyperscript function — the compiled output of JSX.
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
*
* Generic on P so TypeScript validates props match the component's signature
* at the call site, then stores the result in the loosely-typed VNode.
*/
/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
const EMPTY_PROPS = {};
function h(type, props, ...children) {
	return {
		type,
		props: props ?? EMPTY_PROPS,
		children: normalizeChildren(children),
		key: props?.key ?? null
	};
}
function normalizeChildren(children) {
	for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
	return children;
}
function flattenChildren(children) {
	const result = [];
	for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));
	else result.push(child);
	return result;
}
/**
* JSX automatic runtime.
*
* When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
* rewrites JSX to imports from this file automatically:
*   <div class="x" />  →  jsx("div", { class: "x" })
*/
function jsx(type, props, key) {
	const { children, ...rest } = props;
	const propsWithKey = key != null ? {
		...rest,
		key
	} : rest;
	if (typeof type === "function") return h(type, children !== void 0 ? {
		...propsWithKey,
		children
	} : propsWithKey);
	return h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
}

//#endregion
//#region src/chart-component.tsx
/**
* Reactive chart component. Wraps useChart in a div with automatic
* event binding.
*
* @example
* ```tsx
* // Default — any chart type
* <Chart
*   options={() => ({
*     series: [{ type: 'bar', data: revenue() }],
*     tooltip: {},
*   })}
*   style="height: 400px"
* />
*
* // Strict — only specific chart types
* import type { ComposeOption, BarSeriesOption } from '@pyreon/charts'
* <Chart<ComposeOption<BarSeriesOption>>
*   options={() => ({
*     series: [{ type: 'bar', data: revenue() }],
*   })}
*   style="height: 400px"
* />
* ```
*/
function Chart(props) {
	const chart = useChart(props.options, {
		...props.theme != null ? { theme: props.theme } : {},
		...props.renderer != null ? { renderer: props.renderer } : {}
	});
	effect(() => {
		const inst = chart.instance();
		if (!inst) return;
		if (props.onClick) inst.on("click", props.onClick);
		if (props.onMouseover) inst.on("mouseover", props.onMouseover);
		if (props.onMouseout) inst.on("mouseout", props.onMouseout);
	});
	return () => /* @__PURE__ */ jsx("div", {
		ref: chart.ref,
		style: props.style,
		class: props.class
	});
}

//#endregion
export { Chart, useChart };
//# sourceMappingURL=index.js.map