@zkmake/three-meter 0.7.0 → 0.9.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/README.md +109 -71
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{mount-perf-hud-6LeJ93Jg.d.ts → mount-perf-hud-BKpk62Pp.d.ts} +14 -3
- package/dist/{mount-perf-hud-DqY_tP6s.js → mount-perf-hud-CdhGeWXh.js} +269 -18
- package/dist/mount-perf-hud-CdhGeWXh.js.map +1 -0
- package/dist/{performance-monitor-CBN05_BC.d.ts → performance-monitor-DgHxeQ2X.d.ts} +42 -2
- package/dist/{performance-monitor-yxsxs57v.js → performance-monitor-DsBp13ts.js} +204 -1
- package/dist/performance-monitor-DsBp13ts.js.map +1 -0
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/styles.css +104 -0
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +1 -1
- package/package.json +1 -1
- package/dist/mount-perf-hud-DqY_tP6s.js.map +0 -1
- package/dist/performance-monitor-yxsxs57v.js.map +0 -1
|
@@ -486,6 +486,7 @@ const dockPanel = (element, options = {}) => {
|
|
|
486
486
|
//#endregion
|
|
487
487
|
//#region src/ui/icons.ts
|
|
488
488
|
const ICON_MARKUP = {
|
|
489
|
+
flame: "<path d=\"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z\"/>",
|
|
489
490
|
activity: "<path d=\"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2\"/>",
|
|
490
491
|
box: "<path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5\"/><path d=\"M12 22V12\"/>",
|
|
491
492
|
circleDot: "<circle cx=\"12\" cy=\"12\" r=\"10\"/><circle cx=\"12\" cy=\"12\" r=\"1\"/>",
|
|
@@ -526,7 +527,7 @@ const createIcon = (name, className) => {
|
|
|
526
527
|
};
|
|
527
528
|
//#endregion
|
|
528
529
|
//#region package.json
|
|
529
|
-
var version = "0.
|
|
530
|
+
var version = "0.9.0";
|
|
530
531
|
//#endregion
|
|
531
532
|
//#region src/ui/clipboard.ts
|
|
532
533
|
/**
|
|
@@ -604,7 +605,7 @@ const METRIC_HELP = {
|
|
|
604
605
|
//#region src/ui/report.ts
|
|
605
606
|
/**
|
|
606
607
|
* A plain-text snapshot of the monitor for bug reports: versions, backend and
|
|
607
|
-
* GPU, the current sample, stutter stats and the page. Fenced as a `text`
|
|
608
|
+
* GPU, the current sample, stutter stats, the scene's top meshes and the page. Fenced as a `text`
|
|
608
609
|
* code block so GitHub and Slack keep the line breaks.
|
|
609
610
|
*/
|
|
610
611
|
const BACKEND_LABELS = {
|
|
@@ -619,7 +620,13 @@ const backendLabel = (environment) => {
|
|
|
619
620
|
return environment.fallback ? `${label} fallback` : label;
|
|
620
621
|
};
|
|
621
622
|
const ms = (value) => `${value.toFixed(1)} ms`;
|
|
622
|
-
|
|
623
|
+
/** Top meshes by draw calls, three at most: `Top: cubes ×2,000 (1 call, 24K tris) · …`. */
|
|
624
|
+
const topMeshes = (cost) => `Top: ${cost.meshes.slice(0, 3).map((entry) => {
|
|
625
|
+
const copies = entry.instances > 1 ? ` ×${formatCount(entry.instances)}` : "";
|
|
626
|
+
const calls = `${formatCount(entry.calls)} ${entry.calls === 1 ? "call" : "calls"}`;
|
|
627
|
+
return `${entry.label}${copies} (${calls}, ${formatCount(entry.triangles)} tris)`;
|
|
628
|
+
}).join(" · ")}`;
|
|
629
|
+
const renderReport = ({ cost, environment, page, sample, stats }) => {
|
|
623
630
|
const { render, resources } = sample;
|
|
624
631
|
const heading = [
|
|
625
632
|
`three-meter v${version}`,
|
|
@@ -650,6 +657,7 @@ const renderReport = ({ environment, page, sample, stats }) => {
|
|
|
650
657
|
`shaders ${formatCount(resources.programs)}`
|
|
651
658
|
].join(" · ")
|
|
652
659
|
];
|
|
660
|
+
if (cost && cost.meshes.length > 0) lines.push(topMeshes(cost));
|
|
653
661
|
if (page) lines.push(`Viewport ${page.width}×${page.height} @${page.dpr}x`, page.userAgent);
|
|
654
662
|
return [
|
|
655
663
|
"```text",
|
|
@@ -665,6 +673,7 @@ const readPage = () => typeof window === "undefined" ? null : {
|
|
|
665
673
|
};
|
|
666
674
|
/** The report for `monitor` right now, as Markdown ready to paste into an issue. */
|
|
667
675
|
const formatReport = (monitor) => renderReport({
|
|
676
|
+
cost: monitor.getSceneCost(),
|
|
668
677
|
environment: monitor.getEnvironment(),
|
|
669
678
|
page: readPage(),
|
|
670
679
|
sample: monitor.getSample(),
|
|
@@ -778,6 +787,24 @@ const THEME_OPTIONS = [
|
|
|
778
787
|
const RELEASE_URL = `https://github.com/zkmake/three-meter/releases/tag/v${version}`;
|
|
779
788
|
/** How long the report button says `copied` / `failed` before reading `copy` again. */
|
|
780
789
|
const COPY_FEEDBACK_MS = 1500;
|
|
790
|
+
/** Walking the scene graph isn't free; the top-costs list refreshes at 2 Hz while open. */
|
|
791
|
+
const COSTS_INTERVAL_MS = 500;
|
|
792
|
+
const COSTS_ROWS = 5;
|
|
793
|
+
const COST_GROUPS = [{
|
|
794
|
+
group: "meshes",
|
|
795
|
+
label: "meshes"
|
|
796
|
+
}, {
|
|
797
|
+
group: "materials",
|
|
798
|
+
label: "materials"
|
|
799
|
+
}];
|
|
800
|
+
const COSTS_HELP = "The scene's biggest draw costs in the main render pass, estimated from the scene graph. Hidden and off-screen objects are left out; shadow and post-processing passes aren't counted. Click a row to log its objects to the console.";
|
|
801
|
+
/** `×2,000` for instances or copies; nothing for a single object. */
|
|
802
|
+
const copiesOf = (entry) => entry.instances > 1 ? `×${formatCount(entry.instances)}` : "";
|
|
803
|
+
const costTitle = (entry) => {
|
|
804
|
+
const objects = entry.objects.length;
|
|
805
|
+
const shape = entry.instances > objects ? `${formatCount(entry.instances)} instances in ${objects === 1 ? "one object" : `${objects} objects`}` : `${formatCount(objects)} ${objects === 1 ? "object" : "separate objects"}`;
|
|
806
|
+
return `${entry.label}: ${shape}, ${formatCount(entry.calls)} draw ${entry.calls === 1 ? "call" : "calls"}, ${formatCount(entry.triangles)} triangles. Click to log to the console.`;
|
|
807
|
+
};
|
|
781
808
|
const readTiming = (sample, metric) => {
|
|
782
809
|
switch (metric) {
|
|
783
810
|
case "fps": return sample.fps;
|
|
@@ -930,7 +957,6 @@ var PerformanceView = class {
|
|
|
930
957
|
graphCheckboxes = /* @__PURE__ */ new Map();
|
|
931
958
|
statValueEls = /* @__PURE__ */ new Map();
|
|
932
959
|
statCheckboxes = /* @__PURE__ */ new Map();
|
|
933
|
-
dimCheckbox;
|
|
934
960
|
infoCheckbox;
|
|
935
961
|
themeRadios = /* @__PURE__ */ new Map();
|
|
936
962
|
footerThreeEl;
|
|
@@ -947,6 +973,14 @@ var PerformanceView = class {
|
|
|
947
973
|
lastPaintAt = 0;
|
|
948
974
|
resizeObserver;
|
|
949
975
|
unsubscribe;
|
|
976
|
+
costsOpen = false;
|
|
977
|
+
costGroup = "meshes";
|
|
978
|
+
costSort = "calls";
|
|
979
|
+
lastCostsAt = -Infinity;
|
|
980
|
+
costsBodyEl;
|
|
981
|
+
costsListEl;
|
|
982
|
+
costGroupRadios = /* @__PURE__ */ new Map();
|
|
983
|
+
costSortButtons = /* @__PURE__ */ new Map();
|
|
950
984
|
constructor(options) {
|
|
951
985
|
this.monitor = options.monitor;
|
|
952
986
|
this.settings = options.settings ?? new HudSettings();
|
|
@@ -1014,8 +1048,57 @@ var PerformanceView = class {
|
|
|
1014
1048
|
for (const config of TIMINGS) this.paintGraph(config, sample, this.graphValueEls.get(config.metric), this.graphCanvases.get(config.metric), "unavailable");
|
|
1015
1049
|
const stats = this.monitor.getFrameStats();
|
|
1016
1050
|
for (const config of NUMBERS) this.paintNumber(config, this.statValueEls.get(config.key), sample, stats);
|
|
1051
|
+
if (this.costsOpen && performance.now() - this.lastCostsAt >= COSTS_INTERVAL_MS) this.renderCosts();
|
|
1017
1052
|
this.renderFooter();
|
|
1018
1053
|
}
|
|
1054
|
+
renderCosts() {
|
|
1055
|
+
this.lastCostsAt = performance.now();
|
|
1056
|
+
const cost = this.monitor.getSceneCost();
|
|
1057
|
+
if (!cost) {
|
|
1058
|
+
this.costsListEl.replaceChildren(this.costsNote("No scene rendered yet."));
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
const entries = [...this.costGroup === "meshes" ? cost.meshes : cost.materials];
|
|
1062
|
+
if (this.costSort === "triangles") entries.sort((a, b) => b.triangles - a.triangles || b.calls - a.calls);
|
|
1063
|
+
if (entries.length === 0) {
|
|
1064
|
+
this.costsListEl.replaceChildren(this.costsNote("Nothing drawn."));
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const rows = entries.slice(0, COSTS_ROWS).map((entry) => {
|
|
1068
|
+
const row = document.createElement("button");
|
|
1069
|
+
row.type = "button";
|
|
1070
|
+
row.className = "perf-monitor__cost";
|
|
1071
|
+
row.title = costTitle(entry);
|
|
1072
|
+
const name = document.createElement("span");
|
|
1073
|
+
name.className = "perf-monitor__cost-name";
|
|
1074
|
+
name.textContent = entry.label;
|
|
1075
|
+
const copies = copiesOf(entry);
|
|
1076
|
+
if (copies) {
|
|
1077
|
+
const suffix = document.createElement("span");
|
|
1078
|
+
suffix.className = "perf-monitor__cost-copies";
|
|
1079
|
+
suffix.textContent = ` ${copies}`;
|
|
1080
|
+
name.append(suffix);
|
|
1081
|
+
}
|
|
1082
|
+
const calls = document.createElement("span");
|
|
1083
|
+
calls.className = "perf-monitor__cost-value";
|
|
1084
|
+
calls.textContent = formatCount(entry.calls);
|
|
1085
|
+
const triangles = document.createElement("span");
|
|
1086
|
+
triangles.className = "perf-monitor__cost-value";
|
|
1087
|
+
triangles.textContent = formatCount(entry.triangles);
|
|
1088
|
+
row.append(name, calls, triangles);
|
|
1089
|
+
row.addEventListener("click", () => {
|
|
1090
|
+
console.log(`three-meter: ${entry.label}`, entry.objects);
|
|
1091
|
+
});
|
|
1092
|
+
return row;
|
|
1093
|
+
});
|
|
1094
|
+
this.costsListEl.replaceChildren(...rows);
|
|
1095
|
+
}
|
|
1096
|
+
costsNote(text) {
|
|
1097
|
+
const note = document.createElement("div");
|
|
1098
|
+
note.className = "perf-monitor__costs-note";
|
|
1099
|
+
note.textContent = text;
|
|
1100
|
+
return note;
|
|
1101
|
+
}
|
|
1019
1102
|
/** The monitor caches the environment once its backend settles; until then this re-reads. */
|
|
1020
1103
|
renderFooter() {
|
|
1021
1104
|
const environment = this.monitor.getEnvironment();
|
|
@@ -1105,13 +1188,6 @@ var PerformanceView = class {
|
|
|
1105
1188
|
segment.append(radio);
|
|
1106
1189
|
}
|
|
1107
1190
|
themeRow.append(createIcon("contrast", "perf-monitor__icon"), themeLabel, segment);
|
|
1108
|
-
const dimRow = document.createElement("label");
|
|
1109
|
-
dimRow.className = "perf-monitor__row";
|
|
1110
|
-
this.dimCheckbox = this.buildCheckbox(this.settings.dim, "Dim the performance panel when the pointer leaves", (on) => this.settings.setDim(on));
|
|
1111
|
-
const dimLabel = document.createElement("span");
|
|
1112
|
-
dimLabel.className = "perf-monitor__label";
|
|
1113
|
-
dimLabel.textContent = "dim on leave";
|
|
1114
|
-
dimRow.append(createIcon("blend", "perf-monitor__icon"), dimLabel, this.dimCheckbox);
|
|
1115
1191
|
const explainRow = document.createElement("label");
|
|
1116
1192
|
explainRow.className = "perf-monitor__row";
|
|
1117
1193
|
const explainCheckbox = this.buildCheckbox(false, "Explain each metric", (on) => this.element.classList.toggle("perf-monitor--explain", on));
|
|
@@ -1119,7 +1195,7 @@ var PerformanceView = class {
|
|
|
1119
1195
|
explainLabel.className = "perf-monitor__label";
|
|
1120
1196
|
explainLabel.textContent = "explain metrics";
|
|
1121
1197
|
explainRow.append(createIcon("help", "perf-monitor__icon"), explainLabel, explainCheckbox);
|
|
1122
|
-
options.append(themeRow,
|
|
1198
|
+
options.append(themeRow, explainRow, this.buildReportRow());
|
|
1123
1199
|
const graphs = document.createElement("div");
|
|
1124
1200
|
graphs.className = "perf-monitor__graphs";
|
|
1125
1201
|
for (const config of TIMINGS) {
|
|
@@ -1207,7 +1283,7 @@ var PerformanceView = class {
|
|
|
1207
1283
|
this.footerHardwareEl.append(this.footerBackendEl, this.footerGpuEl);
|
|
1208
1284
|
footerBody.append(softwareRow, this.footerHardwareEl);
|
|
1209
1285
|
footer.append(createIcon("info", "perf-monitor__icon"), footerBody, this.infoCheckbox);
|
|
1210
|
-
this.element.append(hud, options, graphs, stats, footer);
|
|
1286
|
+
this.element.append(hud, options, graphs, stats, this.buildCosts(), footer);
|
|
1211
1287
|
}
|
|
1212
1288
|
rebuildHud() {
|
|
1213
1289
|
const { selection } = this.settings;
|
|
@@ -1228,10 +1304,13 @@ var PerformanceView = class {
|
|
|
1228
1304
|
label.className = "perf-monitor__graph-label";
|
|
1229
1305
|
label.textContent = config.label;
|
|
1230
1306
|
label.title = METRIC_HELP[config.metric] ?? "";
|
|
1307
|
+
const head = document.createElement("span");
|
|
1308
|
+
head.className = "perf-monitor__graph-head";
|
|
1309
|
+
head.append(createIcon(config.icon, "perf-monitor__icon"), label);
|
|
1231
1310
|
const value = document.createElement("span");
|
|
1232
1311
|
value.className = "perf-monitor__graph-value";
|
|
1233
1312
|
value.textContent = "—";
|
|
1234
|
-
overlay.append(
|
|
1313
|
+
overlay.append(head, value);
|
|
1235
1314
|
row.append(canvas, overlay);
|
|
1236
1315
|
this.hudGraphsEl.append(row);
|
|
1237
1316
|
const ctx = canvas.getContext("2d");
|
|
@@ -1252,8 +1331,8 @@ var PerformanceView = class {
|
|
|
1252
1331
|
item.className = "perf-monitor__hud-item";
|
|
1253
1332
|
const label = document.createElement("span");
|
|
1254
1333
|
label.className = "perf-monitor__hud-label";
|
|
1255
|
-
label.textContent = config.label;
|
|
1256
1334
|
label.title = METRIC_HELP[config.key] ?? "";
|
|
1335
|
+
label.append(createIcon(config.icon, "perf-monitor__icon"), config.label);
|
|
1257
1336
|
const value = document.createElement("span");
|
|
1258
1337
|
value.className = "perf-monitor__hud-value";
|
|
1259
1338
|
value.textContent = "—";
|
|
@@ -1267,7 +1346,6 @@ var PerformanceView = class {
|
|
|
1267
1346
|
onSelectionChanged() {
|
|
1268
1347
|
for (const [metric, checkbox] of this.graphCheckboxes) checkbox.checked = this.settings.isGraphEnabled(metric);
|
|
1269
1348
|
for (const [key, checkbox] of this.statCheckboxes) checkbox.checked = this.settings.isNumberEnabled(key);
|
|
1270
|
-
this.dimCheckbox.checked = this.settings.dim;
|
|
1271
1349
|
this.infoCheckbox.checked = this.settings.info;
|
|
1272
1350
|
this.applyInfoClass();
|
|
1273
1351
|
this.theme.setOverride(this.settings.theme);
|
|
@@ -1278,6 +1356,71 @@ var PerformanceView = class {
|
|
|
1278
1356
|
applyTheme(this.element, this.theme);
|
|
1279
1357
|
for (const [mode, radio] of this.themeRadios) radio.setAttribute("aria-checked", String(mode === this.theme.effective));
|
|
1280
1358
|
}
|
|
1359
|
+
/** "top costs": a toggle row, then meshes / materials and a sortable top five. */
|
|
1360
|
+
buildCosts() {
|
|
1361
|
+
const section = document.createElement("div");
|
|
1362
|
+
section.className = "perf-monitor__section perf-monitor__costs";
|
|
1363
|
+
const toggleRow = document.createElement("label");
|
|
1364
|
+
toggleRow.className = "perf-monitor__row";
|
|
1365
|
+
toggleRow.title = COSTS_HELP;
|
|
1366
|
+
const label = document.createElement("span");
|
|
1367
|
+
label.className = "perf-monitor__label";
|
|
1368
|
+
label.textContent = "top costs";
|
|
1369
|
+
const checkbox = this.buildCheckbox(false, "Show the scene's biggest draw costs", (on) => {
|
|
1370
|
+
this.costsOpen = on;
|
|
1371
|
+
this.costsBodyEl.hidden = !on;
|
|
1372
|
+
if (on) this.renderCosts();
|
|
1373
|
+
});
|
|
1374
|
+
toggleRow.append(createIcon("flame", "perf-monitor__icon"), label, checkbox);
|
|
1375
|
+
this.costsBodyEl = document.createElement("div");
|
|
1376
|
+
this.costsBodyEl.className = "perf-monitor__costs-body";
|
|
1377
|
+
this.costsBodyEl.hidden = true;
|
|
1378
|
+
const head = document.createElement("div");
|
|
1379
|
+
head.className = "perf-monitor__cost perf-monitor__cost--head";
|
|
1380
|
+
const segment = document.createElement("div");
|
|
1381
|
+
segment.className = "perf-monitor__segment";
|
|
1382
|
+
segment.setAttribute("role", "radiogroup");
|
|
1383
|
+
segment.setAttribute("aria-label", "Group costs by");
|
|
1384
|
+
for (const option of COST_GROUPS) {
|
|
1385
|
+
const radio = document.createElement("button");
|
|
1386
|
+
radio.type = "button";
|
|
1387
|
+
radio.className = "perf-monitor__segment-option perf-monitor__segment-option--text";
|
|
1388
|
+
radio.setAttribute("role", "radio");
|
|
1389
|
+
radio.setAttribute("aria-checked", String(option.group === this.costGroup));
|
|
1390
|
+
radio.textContent = option.label;
|
|
1391
|
+
radio.addEventListener("click", () => {
|
|
1392
|
+
this.costGroup = option.group;
|
|
1393
|
+
for (const [group, button] of this.costGroupRadios) button.setAttribute("aria-checked", String(group === option.group));
|
|
1394
|
+
this.renderCosts();
|
|
1395
|
+
});
|
|
1396
|
+
this.costGroupRadios.set(option.group, radio);
|
|
1397
|
+
segment.append(radio);
|
|
1398
|
+
}
|
|
1399
|
+
head.append(segment);
|
|
1400
|
+
for (const sort of ["calls", "triangles"]) {
|
|
1401
|
+
const button = document.createElement("button");
|
|
1402
|
+
button.type = "button";
|
|
1403
|
+
button.className = "perf-monitor__cost-sort";
|
|
1404
|
+
button.textContent = sort === "calls" ? "calls" : "tris";
|
|
1405
|
+
button.title = `Sort by ${sort === "calls" ? "draw calls" : "triangles"}`;
|
|
1406
|
+
button.setAttribute("aria-pressed", String(sort === this.costSort));
|
|
1407
|
+
button.addEventListener("click", () => {
|
|
1408
|
+
this.costSort = sort;
|
|
1409
|
+
for (const [key, other] of this.costSortButtons) other.setAttribute("aria-pressed", String(key === sort));
|
|
1410
|
+
this.renderCosts();
|
|
1411
|
+
});
|
|
1412
|
+
this.costSortButtons.set(sort, button);
|
|
1413
|
+
head.append(button);
|
|
1414
|
+
}
|
|
1415
|
+
this.costsListEl = document.createElement("div");
|
|
1416
|
+
this.costsListEl.className = "perf-monitor__costs-list";
|
|
1417
|
+
const hint = document.createElement("span");
|
|
1418
|
+
hint.className = "perf-monitor__hint";
|
|
1419
|
+
hint.textContent = COSTS_HELP;
|
|
1420
|
+
this.costsBodyEl.append(head, this.costsListEl, hint);
|
|
1421
|
+
section.append(toggleRow, this.costsBodyEl);
|
|
1422
|
+
return section;
|
|
1423
|
+
}
|
|
1281
1424
|
buildReportRow() {
|
|
1282
1425
|
const row = document.createElement("div");
|
|
1283
1426
|
row.className = "perf-monitor__row perf-monitor__row--static";
|
|
@@ -1574,6 +1717,96 @@ const PERF_HUD_STYLES = `
|
|
|
1574
1717
|
outline-offset: 1px;
|
|
1575
1718
|
}
|
|
1576
1719
|
|
|
1720
|
+
/* Top costs: name, calls, triangles. Rows are buttons that log their objects. */
|
|
1721
|
+
.perf-monitor__costs-body {
|
|
1722
|
+
display: flex;
|
|
1723
|
+
flex-direction: column;
|
|
1724
|
+
gap: 1px;
|
|
1725
|
+
padding-top: 2px;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
.perf-monitor__costs-body[hidden] {
|
|
1729
|
+
display: none;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
.perf-monitor__cost {
|
|
1733
|
+
/* Rows are buttons, which shrink to their content without a width. */
|
|
1734
|
+
box-sizing: border-box;
|
|
1735
|
+
width: 100%;
|
|
1736
|
+
display: grid;
|
|
1737
|
+
grid-template-columns: minmax(0, 1fr) 5ch 6ch;
|
|
1738
|
+
gap: 6px;
|
|
1739
|
+
align-items: baseline;
|
|
1740
|
+
padding: 2px 6px;
|
|
1741
|
+
border: 0;
|
|
1742
|
+
border-radius: 3px;
|
|
1743
|
+
background: transparent;
|
|
1744
|
+
color: inherit;
|
|
1745
|
+
font: inherit;
|
|
1746
|
+
text-align: left;
|
|
1747
|
+
cursor: pointer;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
.perf-monitor__cost:not(.perf-monitor__cost--head):hover {
|
|
1751
|
+
background: var(--perf-row);
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
.perf-monitor__cost:focus-visible {
|
|
1755
|
+
outline: 1px solid color-mix(in srgb, var(--perf-accent) 60%, transparent);
|
|
1756
|
+
outline-offset: -1px;
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
.perf-monitor__cost--head {
|
|
1760
|
+
align-items: center;
|
|
1761
|
+
cursor: default;
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
.perf-monitor__cost-name {
|
|
1765
|
+
overflow: hidden;
|
|
1766
|
+
text-overflow: ellipsis;
|
|
1767
|
+
white-space: nowrap;
|
|
1768
|
+
color: var(--perf-fg-dim);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
.perf-monitor__cost-copies {
|
|
1772
|
+
color: var(--perf-muted);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
.perf-monitor__cost-value {
|
|
1776
|
+
font-variant-numeric: tabular-nums lining-nums;
|
|
1777
|
+
text-align: right;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
.perf-monitor__cost-sort {
|
|
1781
|
+
padding: 0;
|
|
1782
|
+
border: 0;
|
|
1783
|
+
background: transparent;
|
|
1784
|
+
color: var(--perf-muted);
|
|
1785
|
+
font: inherit;
|
|
1786
|
+
font-size: 10px;
|
|
1787
|
+
text-align: right;
|
|
1788
|
+
cursor: pointer;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
.perf-monitor__cost-sort[aria-pressed="true"] {
|
|
1792
|
+
color: var(--perf-fg);
|
|
1793
|
+
text-decoration: underline;
|
|
1794
|
+
text-underline-offset: 2px;
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
.perf-monitor__segment-option--text {
|
|
1798
|
+
width: auto;
|
|
1799
|
+
padding: 0 5px;
|
|
1800
|
+
font: inherit;
|
|
1801
|
+
font-size: 10px;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
.perf-monitor__costs-note {
|
|
1805
|
+
padding: 2px 6px;
|
|
1806
|
+
color: var(--perf-muted);
|
|
1807
|
+
font-size: 10px;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1577
1810
|
.perf-monitor__checkbox {
|
|
1578
1811
|
flex: none;
|
|
1579
1812
|
margin: 0;
|
|
@@ -1630,10 +1863,19 @@ const PERF_HUD_STYLES = `
|
|
|
1630
1863
|
}
|
|
1631
1864
|
|
|
1632
1865
|
.perf-monitor__hud-label {
|
|
1866
|
+
display: inline-flex;
|
|
1867
|
+
align-items: center;
|
|
1868
|
+
gap: 4px;
|
|
1633
1869
|
color: var(--perf-muted);
|
|
1634
1870
|
font-size: 10px;
|
|
1635
1871
|
}
|
|
1636
1872
|
|
|
1873
|
+
.perf-monitor__hud-label .perf-monitor__icon,
|
|
1874
|
+
.perf-monitor__hud-graph .perf-monitor__icon {
|
|
1875
|
+
width: 11px;
|
|
1876
|
+
height: 11px;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1637
1879
|
.perf-monitor__hud-value {
|
|
1638
1880
|
font-weight: 600;
|
|
1639
1881
|
font-variant-numeric: tabular-nums lining-nums;
|
|
@@ -1850,6 +2092,11 @@ const PERF_HUD_STYLES = `
|
|
|
1850
2092
|
outline: 1px solid color-mix(in srgb, var(--perf-accent) 60%, transparent);
|
|
1851
2093
|
outline-offset: 1px;
|
|
1852
2094
|
}
|
|
2095
|
+
|
|
2096
|
+
/* Dim on: the mark takes the accent, so on and off differ even under the hover ring. */
|
|
2097
|
+
.perf-hud__dim[aria-pressed="true"] {
|
|
2098
|
+
color: var(--perf-accent);
|
|
2099
|
+
}
|
|
1853
2100
|
`;
|
|
1854
2101
|
/**
|
|
1855
2102
|
* Append the stylesheet to `target`'s head, once. Call before mounting a view
|
|
@@ -1870,6 +2117,7 @@ const disc = (label, className, icon) => {
|
|
|
1870
2117
|
button.type = "button";
|
|
1871
2118
|
button.className = `perf-hud__disc ${className}`.trim();
|
|
1872
2119
|
button.setAttribute("aria-label", label);
|
|
2120
|
+
button.title = label;
|
|
1873
2121
|
button.append(createIcon(icon, "perf-hud__icon"));
|
|
1874
2122
|
return button;
|
|
1875
2123
|
};
|
|
@@ -1890,7 +2138,9 @@ const mountPerfHud = (monitor, options = {}) => {
|
|
|
1890
2138
|
tools.className = "perf-hud__tools";
|
|
1891
2139
|
const grip = disc("Drag performance panel", "perf-hud__drag", "grip");
|
|
1892
2140
|
const toggle = disc("Toggle full performance metrics", "", "sliders");
|
|
1893
|
-
|
|
2141
|
+
const dim = disc("Dim the panel when the pointer leaves", "perf-hud__dim", "blend");
|
|
2142
|
+
dim.addEventListener("click", () => settings.setDim(!settings.dim));
|
|
2143
|
+
tools.append(grip, toggle, dim);
|
|
1894
2144
|
const view = new PerformanceView({
|
|
1895
2145
|
budgets: options.budgets,
|
|
1896
2146
|
mode: options.mode ?? "compact",
|
|
@@ -1906,6 +2156,7 @@ const mountPerfHud = (monitor, options = {}) => {
|
|
|
1906
2156
|
};
|
|
1907
2157
|
const applyDim = () => {
|
|
1908
2158
|
host.classList.toggle("perf-hud--dim", settings.dim);
|
|
2159
|
+
dim.setAttribute("aria-pressed", String(settings.dim));
|
|
1909
2160
|
};
|
|
1910
2161
|
applyMode();
|
|
1911
2162
|
applyDim();
|
|
@@ -1980,4 +2231,4 @@ const mountPerfHud = (monitor, options = {}) => {
|
|
|
1980
2231
|
//#endregion
|
|
1981
2232
|
export { formatReport as a, HudSettings as c, isThemeMode as d, resolveBudgets as f, PerformanceView as i, HudTheme as l, PERF_HUD_STYLES as n, dockPanel as o, injectStyles as r, DEFAULT_STORAGE_KEY as s, mountPerfHud as t, THEME_MODES as u };
|
|
1982
2233
|
|
|
1983
|
-
//# sourceMappingURL=mount-perf-hud-
|
|
2234
|
+
//# sourceMappingURL=mount-perf-hud-CdhGeWXh.js.map
|