import { n as e, t } from "../utils-C_mWfcFX.js";
import { r as n, t as r } from "../a11y-CuHKgVSx.js";
import { t as i } from "../keyboard-wOEoCCWj.js";
//#region src/charts/base.ts
var a = 600, o = 400, s = {
	top: 20,
	right: 20,
	bottom: 40,
	left: 50
}, c = class {
	canvas;
	ctx;
	container;
	width;
	height;
	padding;
	responsive;
	animate;
	chartId;
	destroyed;
	liveRegion = null;
	resizeObserver;
	boundHandleKeyDown;
	boundHandleFocus;
	boundHandleBlur;
	labelId;
	descId;
	tableId;
	wrapperEl = null;
	accessiblePoints = [];
	focusedPointIndex = -1;
	focusIndicator = null;
	hiddenTable = null;
	chartTitle = "Chart";
	chartDescription = "";
	constructor(r) {
		this.container = t(r.container), this.width = r.width ?? a, this.height = r.height ?? o, this.padding = {
			top: r.padding?.top ?? s.top,
			right: r.padding?.right ?? s.right,
			bottom: r.padding?.bottom ?? s.bottom,
			left: r.padding?.left ?? s.left
		}, this.responsive = r.responsive ?? !1, this.animate = r.animate ?? !1, this.destroyed = !1, typeof window < "u" && this.animate && window.matchMedia("(prefers-reduced-motion: reduce)").matches && (this.animate = !1), this.chartId = e("cmm-chart"), this.labelId = e("cmm-chart-label"), this.descId = e("cmm-chart-desc"), this.tableId = e("cmm-chart-table"), this.resizeObserver = null, this.wrapperEl = document.createElement("div"), this.wrapperEl.className = "cmm-chart-wrapper", this.wrapperEl.style.position = "relative", this.wrapperEl.style.display = "inline-block", this.container.appendChild(this.wrapperEl), this.canvas = document.createElement("canvas"), this.canvas.id = this.chartId, this.canvas.width = this.width, this.canvas.height = this.height, this.canvas.setAttribute("role", "img"), this.canvas.setAttribute("aria-labelledby", this.labelId), this.canvas.setAttribute("aria-describedby", this.descId), this.canvas.setAttribute("tabindex", "0"), this.wrapperEl.appendChild(this.canvas);
		let i = this.canvas.getContext("2d");
		if (i === null) throw Error("Failed to get 2D rendering context");
		this.ctx = i, this.setupCanvas(), r.className !== void 0 && this.canvas.classList.add(r.className), this.createAccessibleElements(), this.createFocusIndicator(), this.liveRegion = n("polite"), this.boundHandleKeyDown = this.handleKeyDown.bind(this), this.boundHandleFocus = this.handleFocus.bind(this), this.boundHandleBlur = this.handleBlur.bind(this), this.canvas.addEventListener("keydown", this.boundHandleKeyDown), this.canvas.addEventListener("focus", this.boundHandleFocus), this.canvas.addEventListener("blur", this.boundHandleBlur), this.responsive && (this.resizeObserver = new ResizeObserver((e) => {
			let t = e[0];
			if (t !== void 0) {
				let { width: e, height: n } = t.contentRect;
				this.resize(Math.round(e), Math.round(n));
			}
		}), this.resizeObserver.observe(this.container));
	}
	get plotArea() {
		return {
			x: this.padding.left,
			y: this.padding.top,
			width: this.width - this.padding.left - this.padding.right,
			height: this.height - this.padding.top - this.padding.bottom
		};
	}
	clear() {
		this.ctx.clearRect(0, 0, this.width, this.height);
	}
	setupCanvas() {
		let e = window.devicePixelRatio === 0 ? 1 : window.devicePixelRatio;
		this.canvas.width = this.width * e, this.canvas.height = this.height * e, this.canvas.style.width = `${String(this.width)}px`, this.canvas.style.height = `${String(this.height)}px`, this.ctx.setTransform(1, 0, 0, 1, 0, 0), this.ctx.scale(e, e);
	}
	resize(e, t) {
		e !== void 0 && (this.width = e), t !== void 0 && (this.height = t), this.setupCanvas(), this.render();
	}
	toDataURL(e) {
		return this.canvas.toDataURL(e);
	}
	destroy() {
		this.resizeObserver !== null && (this.resizeObserver.disconnect(), this.resizeObserver = null), this.canvas.removeEventListener("keydown", this.boundHandleKeyDown), this.canvas.removeEventListener("focus", this.boundHandleFocus), this.canvas.removeEventListener("blur", this.boundHandleBlur), this.liveRegion?.destroy(), this.liveRegion = null, this.wrapperEl !== null && this.wrapperEl.remove(), this.destroyed = !0;
	}
	createAccessibleElements() {
		if (this.wrapperEl === null) return;
		let e = document.createElement("span");
		e.id = this.labelId, e.className = "cmm-sr-only", e.style.cssText = "\n      position: absolute;\n      width: 1px;\n      height: 1px;\n      padding: 0;\n      margin: -1px;\n      overflow: hidden;\n      clip: rect(0, 0, 0, 0);\n      white-space: nowrap;\n      border: 0;\n    ", this.wrapperEl.appendChild(e);
		let t = document.createElement("span");
		t.id = this.descId, t.className = "cmm-sr-only", t.style.cssText = e.style.cssText, this.wrapperEl.appendChild(t);
		let n = document.createElement("div");
		n.id = this.tableId, n.className = "cmm-sr-only", n.style.cssText = e.style.cssText, this.hiddenTable = n, this.wrapperEl.appendChild(n);
	}
	createFocusIndicator() {
		if (this.wrapperEl === null) return;
		let e = document.createElement("div");
		e.className = "cmm-chart-focus-indicator", e.style.cssText = "\n      position: absolute;\n      width: 12px;\n      height: 12px;\n      border: 2px solid hsl(var(--focus-ring, 189 94% 43%));\n      border-radius: 50%;\n      background: hsl(var(--focus-ring, 189 94% 43%) / 0.3);\n      pointer-events: none;\n      display: none;\n      transform: translate(-50%, -50%);\n      z-index: 10;\n    ", e.setAttribute("aria-hidden", "true"), this.focusIndicator = e, this.wrapperEl.appendChild(e);
	}
	updateAccessibleInfo() {
		let e = document.getElementById(this.labelId), t = document.getElementById(this.descId);
		if (e !== null && (e.textContent = this.chartTitle), t !== null) {
			let e = this.accessiblePoints.length;
			t.textContent = this.chartDescription === "" ? `Interactive chart with ${String(e)} data points. Use arrow keys to navigate between data points.` : this.chartDescription;
		}
	}
	setAccessiblePoints(e) {
		this.accessiblePoints = e, this.focusedPointIndex = -1, this.updateAccessibleInfo(), this.updateHiddenTable();
	}
	updateHiddenTable() {
		if (this.hiddenTable === null || (this.hiddenTable.innerHTML = "", this.accessiblePoints.length === 0)) return;
		let e = document.createElement("table");
		e.setAttribute("role", "table"), e.setAttribute("aria-label", `Data for ${this.chartTitle}`);
		let t = this.accessiblePoints.some((e) => e.series !== void 0), n = document.createElement("thead"), r = document.createElement("tr");
		if (t) {
			let e = document.createElement("th");
			e.setAttribute("scope", "col"), e.textContent = "Series", r.appendChild(e);
		}
		let i = document.createElement("th");
		i.setAttribute("scope", "col"), i.textContent = "Label", r.appendChild(i);
		let a = document.createElement("th");
		a.setAttribute("scope", "col"), a.textContent = "Value", r.appendChild(a), n.appendChild(r), e.appendChild(n);
		let o = document.createElement("tbody");
		for (let e of this.accessiblePoints) {
			let n = document.createElement("tr");
			if (t) {
				let t = document.createElement("td");
				t.textContent = e.series ?? "", n.appendChild(t);
			}
			let r = document.createElement("td");
			r.textContent = e.label, n.appendChild(r);
			let i = document.createElement("td");
			i.textContent = String(e.value), n.appendChild(i), o.appendChild(n);
		}
		e.appendChild(o), this.hiddenTable.appendChild(e);
	}
	handleKeyDown(e) {
		if (this.accessiblePoints.length === 0) return;
		let t = !1, n = this.focusedPointIndex;
		switch (e.key) {
			case i.ARROW_RIGHT:
			case i.ARROW_DOWN:
				n = this.focusedPointIndex + 1, n >= this.accessiblePoints.length && (n = 0), t = !0;
				break;
			case i.ARROW_LEFT:
			case i.ARROW_UP:
				n = this.focusedPointIndex - 1, n < 0 && (n = this.accessiblePoints.length - 1), t = !0;
				break;
			case i.HOME:
				n = 0, t = !0;
				break;
			case i.END:
				n = this.accessiblePoints.length - 1, t = !0;
				break;
			case i.ENTER:
			case i.SPACE:
				if (this.focusedPointIndex >= 0) {
					let e = this.accessiblePoints[this.focusedPointIndex];
					e !== void 0 && this.onPointActivated(e);
				}
				t = !0;
				break;
		}
		t && (e.preventDefault(), n !== this.focusedPointIndex && n >= 0 && (this.focusedPointIndex = n, this.updateFocusIndicator(), this.announcePoint()));
	}
	handleFocus() {
		this.accessiblePoints.length > 0 && this.focusedPointIndex < 0 && (this.focusedPointIndex = 0, this.updateFocusIndicator(), this.announcePoint());
	}
	handleBlur() {
		this.hideFocusIndicator();
	}
	updateFocusIndicator() {
		if (this.focusIndicator === null || this.focusedPointIndex < 0) {
			this.hideFocusIndicator();
			return;
		}
		let e = this.accessiblePoints[this.focusedPointIndex];
		if (e === void 0) {
			this.hideFocusIndicator();
			return;
		}
		this.focusIndicator.style.display = "block", this.focusIndicator.style.left = `${String(e.x)}px`, this.focusIndicator.style.top = `${String(e.y)}px`;
	}
	hideFocusIndicator() {
		this.focusIndicator !== null && (this.focusIndicator.style.display = "none");
	}
	announcePoint() {
		if (this.focusedPointIndex < 0) return;
		let e = this.accessiblePoints[this.focusedPointIndex];
		if (e === void 0) return;
		let t = `${String(this.focusedPointIndex + 1)} of ${String(this.accessiblePoints.length)}`, n = `${e.label}: ${String(e.value)}`;
		e.series !== void 0 && (n = `${e.series}, ${n}`), n += `. Point ${t}`, r(n, "polite");
	}
	onPointActivated(e) {
		r(`${e.label} selected`, "polite");
	}
	generateAccessiblePoint(e, t, n, r, i, a, o) {
		let s = {
			id: e,
			x: t,
			y: n,
			label: r,
			value: i,
			data: a
		};
		return o !== void 0 && (s.series = o), s;
	}
};
//#endregion
export { c as BaseChart };

//# sourceMappingURL=base.js.map