Files
microsoft--agent-lightning/docs/javascripts/charts.js
T
wehub-resource-sync 85742ab165
CPU Test / Lint - next (push) Waiting to run
Dashboard / Chromatic (push) Waiting to run
CPU Test / Lint - fast (push) Waiting to run
CPU Test / Build documentation (push) Waiting to run
CPU Test / Test (Store, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (Utilities, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (Weave, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (AgentOps, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (LLM proxy, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (Others, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (Store, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (Utilities, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (Weave, stable, Python 3.11) (push) Waiting to run
CPU Test / Test (AgentOps, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (LLM proxy, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (Others, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (Store, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (Utilities, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (Weave, stable, Python 3.12) (push) Waiting to run
CPU Test / Test (AgentOps, latest, Python 3.13) (push) Waiting to run
CPU Test / Test (LLM proxy, latest, Python 3.13) (push) Waiting to run
CPU Test / Test (Others, latest, Python 3.13) (push) Waiting to run
CPU Test / Test (Store, latest, Python 3.13) (push) Waiting to run
CPU Test / Lint - slow (push) Waiting to run
CPU Test / Lint - JavaScript (push) Waiting to run
CPU Test / Test (AgentOps, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (LLM proxy, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (Others, legacy, Python 3.10) (push) Waiting to run
CPU Test / Test (Utilities, latest, Python 3.13) (push) Waiting to run
CPU Test / Test (Weave, latest, Python 3.13) (push) Waiting to run
CPU Test / Test (JavaScript) (push) Waiting to run
Deploy Documentation / deploy (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:44:17 +08:00

226 lines
7.1 KiB
JavaScript

// Copyright (c) Microsoft. All rights reserved.
// ---- CSS helpers ---------------------------------------------------------
function matVar(name) {
return getComputedStyle(document.body).getPropertyValue(name).trim();
}
function toRGBA(color, a = 1) {
if (!color) return `rgba(0,0,0,${a})`;
const m = color.match(/^#?([\da-f]{3}|[\da-f]{6})$/i);
if (m) {
const hex = m[1].length === 3 ? m[1].split("").map((x) => x + x).join("") : m[1];
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
const nums = color.match(/[\d.]+/g) || [0, 0, 0, 1];
const [r, g, b] = nums.map(Number);
return `rgba(${r | 0}, ${g | 0}, ${b | 0}, ${a})`;
}
// ---- Theme defaults (pulled from MkDocs Material CSS vars) ---------------
function applyThemeDefaults() {
const font = matVar("--md-text-font").replace(/['"]/g, "") || "Roboto, sans-serif";
const text = matVar("--md-default-fg-color") || "#1f2937";
const border = "rgba(128, 128, 128, 0.1)"
const bg = "#777777";
Chart.defaults.font.family = font;
Chart.defaults.font.size = 16;
Chart.defaults.color = text;
Chart.defaults.borderColor = border;
Chart.defaults.backgroundColor = bg;
Chart.defaults.scale.grid.color = border;
Chart.defaults.scale.ticks.color = text;
Chart.defaults.scale.title.color = text;
Chart.defaults.plugins.legend.labels.color = text;
Chart.defaults.plugins.tooltip.titleColor = text;
Chart.defaults.plugins.tooltip.bodyColor = text;
Chart.defaults.plugins.tooltip.backgroundColor = toRGBA(bg, 0.5);
Chart.defaults.plugins.tooltip.borderColor = border;
Chart.defaults.plugins.tooltip.borderWidth = 1;
Chart.defaults.responsive = true;
Chart.defaults.maintainAspectRatio = false;
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
Chart.defaults.animation = false;
}
}
// ---- Dataset color defaults (Material primary/accent) --------------------
const colorScheme = ["#c45259", "#5276c4", "#f69047", "#7cc452", "#c2b00a"];
function applyDatasetDefaults(config) {
if (!config.data || !Array.isArray(config.data.datasets)) return;
config.data.datasets = config.data.datasets.map((ds, index) => {
const color = colorScheme[index % colorScheme.length];
return {
...ds,
borderColor: toRGBA(color, 0.8),
backgroundColor: toRGBA(color, 0.3),
pointBackgroundColor: color,
pointBorderColor: color,
};
});
}
// ---- Deep merge (config JSON + our defaults) ----------------------------
function deepMerge(target, src) {
if (!src || typeof src !== "object") return target;
for (const k of Object.keys(src)) {
const v = src[k];
if (v && typeof v === "object" && !Array.isArray(v)) {
target[k] = deepMerge(target[k] || {}, v);
} else {
target[k] = v;
}
}
return target;
}
// ---- Build final config for a canvas ------------------------------------
function buildConfig(baseCfg) {
const globalDefaults = {
options: {
responsive: true,
maintainAspectRatio: false,
interaction: { mode: "index", intersect: false },
plugins: {
legend: { position: "top" },
tooltip: { enabled: true },
},
layout: { padding: { top: 8, right: 8, bottom: 0, left: 0 } },
normalized: true,
alignToPixels: true,
animations: {
y: {
from: (ctx) => 300,
duration: 1500,
easing: "easeOutCubic",
},
radius: {
from: 0,
to: 3,
duration: 300,
delay: (ctx) => ctx.dataIndex * 30,
},
},
elements: { line: { tension: 0.3 } },
},
};
const merged = deepMerge({}, globalDefaults);
applyDatasetDefaults(baseCfg);
deepMerge(merged, baseCfg); // user config wins
return merged;
}
(function () {
// registry stores per-canvas state: { chart, cfg }
const registry = new WeakMap(); // canvas -> { chart, cfg }
// IntersectionObserver to (re)animate when visible
const io = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
const canvas = entry.target;
const state = registry.get(canvas);
if (!state || !state.cfg) return;
// Respect reduced-motion: if disabled, just update without animation
const prefersReduced =
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
// Destroy & rebuild to guarantee a fresh animation
if (state.chart) {
try {
state.chart.destroy();
} catch (_) {}
}
const ctx = canvas.getContext("2d");
const cfg = buildConfig(JSON.parse(JSON.stringify(state.cfg)));
// If reduced motion, skip animations
if (prefersReduced) {
cfg.options = cfg.options || {};
cfg.options.animation = false;
}
state.chart = new Chart(ctx, cfg);
registry.set(canvas, state);
});
},
{ threshold: 0.3 } // animate when ~30% visible
);
// ---- Render all canvases with data-chart JSON ---------------------------
function renderAll() {
document.querySelectorAll("canvas[data-chart]").forEach((canvas) => {
let parsedCfg;
try {
parsedCfg = JSON.parse(canvas.getAttribute("data-chart"));
} catch (e) {
console.error("Invalid data-chart JSON:", e, canvas);
return;
}
// store config; chart will be created by IntersectionObserver when visible
if (!registry.get(canvas)) {
registry.set(canvas, { chart: null, cfg: parsedCfg });
io.observe(canvas);
}
});
}
// ---- Retheme on scheme/primary/accent change ----------------------------
function retheme() {
applyThemeDefaults();
// Update visible charts without forcing animation
document.querySelectorAll("canvas[data-chart]").forEach((c) => {
const state = registry.get(c);
if (state?.chart) {
// Fix the issue that scale options color are not updated when theme changes
const scaleOptions = state.chart.options.scales;
for (const key of Object.keys(scaleOptions)) {
scaleOptions[key].ticks.color = Chart?.defaults?.scale?.ticks?.color;
scaleOptions[key].title.color = Chart?.defaults?.scale?.title?.color;
}
state.chart.update("none");
}
});
}
// Initial theme + render (works on hard refresh)
function boot() {
applyThemeDefaults();
renderAll();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", boot);
} else {
boot();
}
// Observe theme flips. Attributes might be on <html> or <body>.
const attrs = ["data-md-color-scheme", "data-md-color-primary", "data-md-color-accent"];
const obs = new MutationObserver(retheme);
obs.observe(document.documentElement, {
attributes: true,
attributeFilter: attrs,
subtree: true,
});
// Re-scan on SPA navigations (Material)
if (typeof document$ !== "undefined" && document$.subscribe) {
document$.subscribe(() => {
renderAll(); // new canvases
retheme(); // keep colors in sync
});
}
})();