@flemo/devtools 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/README.md +7 -5
- package/dist/__tests__/swipeProbe.test.d.ts +1 -0
- package/dist/hud.d.ts +14 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.mjs +308 -229
- package/dist/noop.d.ts +5 -1
- package/dist/noop.mjs +7 -9
- package/dist/panel/styles.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.mjs +394 -372
- package/dist/surface.d.ts +0 -8
- package/dist/swipeProbe.d.ts +52 -0
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -174,7 +174,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
174
174
|
}), oe = (e) => e.some((e) => {
|
|
175
175
|
let t = e.getAttribute(m);
|
|
176
176
|
return t !== null && L.has(t);
|
|
177
|
-
}),
|
|
177
|
+
}), R = (e) => `${e.transform}/${e.opacity}`, se = (e, t, n) => {
|
|
178
178
|
e.releasedFrames += 1;
|
|
179
179
|
let r = !1, i = !1;
|
|
180
180
|
for (let n of t) {
|
|
@@ -188,7 +188,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
let a = n.style;
|
|
191
|
-
a && a.animation !== "" && e.lastPose.get(n) !==
|
|
191
|
+
a && a.animation !== "" && e.lastPose.get(n) !== R(a) && (r = !0);
|
|
192
192
|
}
|
|
193
193
|
if (!(e.releasedFrames < re)) {
|
|
194
194
|
if (r) {
|
|
@@ -201,17 +201,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
201
201
|
}
|
|
202
202
|
e.stalledFrames += 1, e.stallRunMs += n, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
|
|
203
203
|
}
|
|
204
|
-
},
|
|
204
|
+
}, z = (e, t) => {
|
|
205
205
|
let n = t.style;
|
|
206
206
|
if (!n || n.animation === "") return;
|
|
207
207
|
e.evidence.inlineSuppression = !0;
|
|
208
|
-
let r =
|
|
208
|
+
let r = R(n), i = e.lastPose.get(t);
|
|
209
209
|
i !== void 0 && i !== r && (e.evidence.inlineAdvance = !0), e.lastPose.set(t, r);
|
|
210
|
-
},
|
|
210
|
+
}, B = (e, t) => {
|
|
211
211
|
for (let n of t) {
|
|
212
212
|
let t = n.getAnimations, r = e.clocks.get(n);
|
|
213
213
|
if (r !== void 0 && r.playState !== "finished") {
|
|
214
|
-
r.playState === "running" && (e.evidence.compiledAnimation = !0),
|
|
214
|
+
r.playState === "running" && (e.evidence.compiledAnimation = !0), z(e, n);
|
|
215
215
|
continue;
|
|
216
216
|
}
|
|
217
217
|
if (typeof t == "function") try {
|
|
@@ -220,40 +220,40 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
220
220
|
typeof t == "string" && t.startsWith("flemo-") && (e.clocks.set(n, r), r.playState === "running" && (e.evidence.compiledAnimation = !0));
|
|
221
221
|
}
|
|
222
222
|
} catch {}
|
|
223
|
-
|
|
223
|
+
z(e, n);
|
|
224
224
|
}
|
|
225
|
-
},
|
|
225
|
+
}, ce = (e) => ({
|
|
226
226
|
sampledFrames: e.releasedFrames,
|
|
227
227
|
stalledFrames: e.stalledFrames,
|
|
228
228
|
longestStallMs: ie(e.longestStallMs),
|
|
229
229
|
pausedAfterRelease: e.pausedAfterRelease,
|
|
230
230
|
holdReassertedAtMs: e.holdReassertedAtMs,
|
|
231
231
|
tailFrames: e.tailFrames
|
|
232
|
-
}),
|
|
232
|
+
}), V = 200, H = (e) => {
|
|
233
233
|
let t = [];
|
|
234
234
|
for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
|
|
235
235
|
return t;
|
|
236
|
-
},
|
|
237
|
-
let t = new Set(
|
|
236
|
+
}, le = (e) => {
|
|
237
|
+
let t = new Set(H(e).filter((e) => !e.complete));
|
|
238
238
|
return {
|
|
239
239
|
tracked: t,
|
|
240
240
|
loadingAtStart: t.size,
|
|
241
241
|
addedDuringFlight: 0,
|
|
242
242
|
held: /* @__PURE__ */ new Set()
|
|
243
243
|
};
|
|
244
|
-
},
|
|
245
|
-
if (!(e.tracked.size >=
|
|
244
|
+
}, ue = (e, t, n) => {
|
|
245
|
+
if (!(e.tracked.size >= V)) for (let r of Array.from(n)) {
|
|
246
246
|
if (!(r instanceof Element) || !t.some((e) => e === r || e.contains(r))) continue;
|
|
247
247
|
let n = r instanceof HTMLImageElement ? [r] : Array.from(r.querySelectorAll("img"));
|
|
248
248
|
for (let t of n) if (!(t.complete || e.tracked.has(t))) {
|
|
249
|
-
if (e.tracked.size >=
|
|
249
|
+
if (e.tracked.size >= V) return;
|
|
250
250
|
e.tracked.add(t), e.addedDuringFlight += 1;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
-
},
|
|
253
|
+
}, de = (e, t) => {
|
|
254
254
|
for (let n of t) for (let t of Array.from(n.querySelectorAll(`img[${h}]`))) e.held.add(t);
|
|
255
255
|
for (let t of e.tracked) t.hasAttribute("data-flemo-img-hold") && e.held.add(t);
|
|
256
|
-
},
|
|
256
|
+
}, fe = (e) => {
|
|
257
257
|
let t = 0, n = 0;
|
|
258
258
|
for (let r of e.tracked) r.complete && (t += 1, e.held.has(r) || (n += 1));
|
|
259
259
|
return {
|
|
@@ -263,12 +263,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
263
263
|
heldDuringFlight: e.held.size,
|
|
264
264
|
completedUnheld: n
|
|
265
265
|
};
|
|
266
|
-
},
|
|
266
|
+
}, pe = [
|
|
267
267
|
"DevTools must be CLOSED while judging motion. An open inspector serializes requests and repaints its own panels on the same machine; the 2026-08 campaign's entire residual 'stutter' was this, and it is invisible to every in-page metric.",
|
|
268
268
|
"No screen recording or display capture while judging. A capture client forces WindowServer to composite every vsync, which SUPPRESSES the symptom — a capture that looks smooth proves nothing about the uncaptured session.",
|
|
269
269
|
"Judge with real input (a finger, a mouse). Synthetic dispatch — evaluate().click() and friends — never fires pointerdown, so it bypasses the swipe/gesture machinery that a real navigation goes through.",
|
|
270
270
|
"Establish the viewing configuration before believing any verdict: device emulation off, which physical display, its refresh rate and HiDPI scaling, Low Power Mode. Ask for a photo of the setup if it is not certain."
|
|
271
|
-
],
|
|
271
|
+
], U = (e) => Math.round(e * 10) / 10, me = (e) => {
|
|
272
272
|
if (e.length === 0) return {
|
|
273
273
|
count: 0,
|
|
274
274
|
medianGapMs: 0,
|
|
@@ -278,11 +278,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
278
278
|
let t = [...e].sort((e, t) => e - t);
|
|
279
279
|
return {
|
|
280
280
|
count: e.length,
|
|
281
|
-
medianGapMs:
|
|
282
|
-
maxGapMs:
|
|
281
|
+
medianGapMs: U(t[Math.floor(t.length / 2)]),
|
|
282
|
+
maxGapMs: U(t[t.length - 1]),
|
|
283
283
|
over30Count: e.filter((e) => e >= 30).length
|
|
284
284
|
};
|
|
285
|
-
},
|
|
285
|
+
}, he = (e, t = []) => {
|
|
286
286
|
let n = [...e, ...t];
|
|
287
287
|
return {
|
|
288
288
|
...n.length === 0 ? {
|
|
@@ -293,18 +293,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
293
293
|
let e = [...n].sort((e, t) => e - t);
|
|
294
294
|
return {
|
|
295
295
|
count: n.length,
|
|
296
|
-
medianGapMs:
|
|
297
|
-
maxGapMs:
|
|
296
|
+
medianGapMs: U(e[Math.floor(e.length / 2)]),
|
|
297
|
+
maxGapMs: U(e[e.length - 1])
|
|
298
298
|
};
|
|
299
299
|
})(),
|
|
300
|
-
longGaps: n.filter((e) => e >= 30).map(
|
|
301
|
-
held:
|
|
302
|
-
released:
|
|
300
|
+
longGaps: n.filter((e) => e >= 30).map(U),
|
|
301
|
+
held: me(e),
|
|
302
|
+
released: me(t)
|
|
303
303
|
};
|
|
304
|
-
},
|
|
304
|
+
}, ge = (e) => {
|
|
305
305
|
let t = e.inlineSuppression || e.inlineAdvance;
|
|
306
306
|
return t && e.compiledAnimation ? "mixed" : t ? "inline" : e.compiledAnimation ? "compiled" : "unknown";
|
|
307
|
-
},
|
|
307
|
+
}, _e = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ve = (e) => {
|
|
308
308
|
let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
|
|
309
309
|
if (t) {
|
|
310
310
|
let e = t[1].split(",").map((e) => Number(e.trim()));
|
|
@@ -316,7 +316,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
316
316
|
return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
|
|
317
317
|
}
|
|
318
318
|
return null;
|
|
319
|
-
},
|
|
319
|
+
}, W = (e) => {
|
|
320
320
|
if (e) return [];
|
|
321
321
|
let t = [];
|
|
322
322
|
for (let [e, n] of [[h, "image reveal hold"], [g, "arrival hold"]]) {
|
|
@@ -324,7 +324,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
324
324
|
r > 0 && t.push(`${r} × ${n} (${e}) still marked at rest`);
|
|
325
325
|
}
|
|
326
326
|
return t;
|
|
327
|
-
},
|
|
327
|
+
}, ye = (e, t) => {
|
|
328
328
|
let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
|
|
329
329
|
return e.forEach((e, t) => {
|
|
330
330
|
if (!(e instanceof HTMLElement) || !e.isConnected) return;
|
|
@@ -336,27 +336,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
336
336
|
if (o === "none") return;
|
|
337
337
|
let s = e.getAttribute(p) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
|
|
338
338
|
if (e.style.transform !== "" && e.style.transform !== "none" && n.push(`${c} transform=${e.style.transform}`), e.style.opacity !== "" && e.style.opacity !== "1" && n.push(`${c} opacity=${e.style.opacity}`), s && e.getAttribute("data-flemo-status") === "COMPLETED" && i > 0) {
|
|
339
|
-
let e =
|
|
339
|
+
let e = ve(a);
|
|
340
340
|
e !== null && Math.abs(e) >= i * .5 && (r = !0);
|
|
341
341
|
}
|
|
342
342
|
}), {
|
|
343
343
|
residualInlineTransforms: n,
|
|
344
344
|
offViewportAtRest: r,
|
|
345
|
-
orphanedHolds:
|
|
345
|
+
orphanedHolds: W(t)
|
|
346
346
|
};
|
|
347
|
-
},
|
|
347
|
+
}, be = E.map((e) => `[${b}="${e}"]`).join(","), xe = A(d), Se = (e) => Math.round(e * 10) / 10, Ce = (e) => {
|
|
348
348
|
let t = e.getAttribute(x);
|
|
349
349
|
return t === null || t === "" ? null : t;
|
|
350
|
-
},
|
|
350
|
+
}, we = (e) => {
|
|
351
351
|
let t = e.getAttribute(b);
|
|
352
352
|
return t !== null && E.includes(t);
|
|
353
|
-
},
|
|
353
|
+
}, Te = () => {
|
|
354
354
|
try {
|
|
355
355
|
return document.querySelector("style[data-flemo-morph-sheet]")?.sheet?.cssRules.length ?? 0;
|
|
356
356
|
} catch {
|
|
357
357
|
return 0;
|
|
358
358
|
}
|
|
359
|
-
},
|
|
359
|
+
}, Ee = (e) => {
|
|
360
360
|
let t = {
|
|
361
361
|
registered: 0,
|
|
362
362
|
pairable: /* @__PURE__ */ new Set(),
|
|
@@ -366,17 +366,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
366
366
|
ghosts: 0,
|
|
367
367
|
ghostBornAt: /* @__PURE__ */ new Map(),
|
|
368
368
|
shortestGhostLifeMs: null,
|
|
369
|
-
sheetRulesAtStart:
|
|
369
|
+
sheetRulesAtStart: Te()
|
|
370
370
|
}, n = new Set(e), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
|
|
371
371
|
for (let e of Array.from(document.querySelectorAll(A(b)))) {
|
|
372
372
|
t.registered += 1;
|
|
373
|
-
let a =
|
|
373
|
+
let a = Ce(e);
|
|
374
374
|
if (a === null) continue;
|
|
375
|
-
if (
|
|
375
|
+
if (we(e)) {
|
|
376
376
|
t.flew.add(a);
|
|
377
377
|
continue;
|
|
378
378
|
}
|
|
379
|
-
let o = e.closest(
|
|
379
|
+
let o = e.closest(xe);
|
|
380
380
|
if (o !== null && !n.has(o)) continue;
|
|
381
381
|
let s = o, c = r.get(a);
|
|
382
382
|
c || r.set(a, c = /* @__PURE__ */ new Set()), c.add(s);
|
|
@@ -389,27 +389,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
389
389
|
r && [...r.values()].some((e) => e > 1) && t.duplicated.add(e);
|
|
390
390
|
}
|
|
391
391
|
return t;
|
|
392
|
-
},
|
|
393
|
-
if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !
|
|
394
|
-
let n =
|
|
392
|
+
}, De = (e, t) => {
|
|
393
|
+
if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !we(t)) return;
|
|
394
|
+
let n = Ce(t);
|
|
395
395
|
n !== null && e.flew.add(n);
|
|
396
|
-
},
|
|
397
|
-
for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of
|
|
398
|
-
for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of
|
|
396
|
+
}, Oe = (e, t, n) => {
|
|
397
|
+
for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of ke(r)) e.ghostBornAt.has(t) || (e.ghosts += 1, e.ghostBornAt.set(t, n));
|
|
398
|
+
for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of ke(r)) {
|
|
399
399
|
let r = e.ghostBornAt.get(t);
|
|
400
400
|
if (r === void 0) continue;
|
|
401
401
|
e.ghostBornAt.delete(t);
|
|
402
402
|
let i = n - r;
|
|
403
403
|
(e.shortestGhostLifeMs === null || i < e.shortestGhostLifeMs) && (e.shortestGhostLifeMs = i);
|
|
404
404
|
}
|
|
405
|
-
},
|
|
405
|
+
}, ke = (e) => [...e.hasAttribute("data-flemo-morph-ghost") ? [e] : [], ...Array.from(e.querySelectorAll(A(w)))], Ae = (e) => {
|
|
406
406
|
let t = e.shortestGhostLifeMs;
|
|
407
407
|
return t === null || t >= 34 ? [] : [{
|
|
408
408
|
kind: "ghost-cut",
|
|
409
|
-
atMs:
|
|
410
|
-
detail: `a morph ghost was removed ${
|
|
409
|
+
atMs: Se(t),
|
|
410
|
+
detail: `a morph ghost was removed ${Se(t)}ms after it was created (under one frame) — the departing content it stands for was never presented; this is the first-frame blade signature`
|
|
411
411
|
}];
|
|
412
|
-
},
|
|
412
|
+
}, je = (e, t) => {
|
|
413
413
|
let n = [...e.pairable].sort(), r = [...e.flew].sort(), i = new Set(r), a = t ? {
|
|
414
414
|
strandedRoles: 0,
|
|
415
415
|
strandedStandIns: 0,
|
|
@@ -417,11 +417,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
417
417
|
layerResidue: 0,
|
|
418
418
|
leaked: 0
|
|
419
419
|
} : {
|
|
420
|
-
strandedRoles: document.querySelectorAll(
|
|
420
|
+
strandedRoles: document.querySelectorAll(be).length,
|
|
421
421
|
strandedStandIns: document.querySelectorAll(A(C)).length,
|
|
422
422
|
strandedGhosts: document.querySelectorAll(A(w)).length,
|
|
423
423
|
layerResidue: Array.from(document.querySelectorAll(A(S))).reduce((e, t) => e + t.childElementCount, 0),
|
|
424
|
-
leaked: Math.max(0,
|
|
424
|
+
leaked: Math.max(0, Te() - e.sheetRulesAtStart)
|
|
425
425
|
};
|
|
426
426
|
return {
|
|
427
427
|
registered: e.registered,
|
|
@@ -437,21 +437,19 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
437
437
|
layerResidue: a.layerResidue,
|
|
438
438
|
duplicatedKeys: [...e.duplicated].sort()
|
|
439
439
|
};
|
|
440
|
-
},
|
|
441
|
-
key:
|
|
442
|
-
storage: "session",
|
|
443
|
-
kind: "opt-in-diagnostic",
|
|
444
|
-
values: "\"on\" / \"off\"",
|
|
445
|
-
fallback: "off",
|
|
446
|
-
effect: "arms this flight recorder in the playground (?devtools=on)"
|
|
447
|
-
}, {
|
|
448
|
-
key: U,
|
|
440
|
+
}, Me = "flemo:devtools-panel-height", Ne = [{
|
|
441
|
+
key: Me,
|
|
449
442
|
storage: "session",
|
|
450
443
|
kind: "production-state",
|
|
451
444
|
values: "a pixel height",
|
|
452
445
|
fallback: "(the panel's default height)",
|
|
453
446
|
effect: "the drawer height this panel was last dragged to"
|
|
454
|
-
}],
|
|
447
|
+
}], Pe = [], Fe = [...Pe, ...Ne], G = [
|
|
448
|
+
{
|
|
449
|
+
key: "flemo:devtools",
|
|
450
|
+
storage: "session",
|
|
451
|
+
retiredWith: "the playground's opt-in. `<FlemoDevtools />` mounts unconditionally and a production build resolves it to the inert entry, so there is nothing to arm (2026-09-07)"
|
|
452
|
+
},
|
|
455
453
|
{
|
|
456
454
|
key: "flemo:sixty",
|
|
457
455
|
storage: "session",
|
|
@@ -585,9 +583,9 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
585
583
|
} catch {
|
|
586
584
|
return null;
|
|
587
585
|
}
|
|
588
|
-
}, ze = new Set(
|
|
586
|
+
}, ze = new Set(Fe.map((e) => e.key)), Be = new Set(G.map((e) => e.key)), Ve = () => {
|
|
589
587
|
let e = {}, t = Le("session"), n = Le("local");
|
|
590
|
-
for (let r of
|
|
588
|
+
for (let r of Fe) {
|
|
591
589
|
let i = Re(r.storage === "session" ? t : n, r.key);
|
|
592
590
|
i !== null && (e[r.key] = i);
|
|
593
591
|
}
|
|
@@ -900,7 +898,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
900
898
|
previousSession: null,
|
|
901
899
|
anomalies: [],
|
|
902
900
|
blindSpots: [...c],
|
|
903
|
-
judgingProtocol: [...
|
|
901
|
+
judgingProtocol: [...pe]
|
|
904
902
|
}), Ct = (e = {}) => {
|
|
905
903
|
if (xt) return xt;
|
|
906
904
|
if (typeof window > "u" || typeof document > "u") return {
|
|
@@ -960,17 +958,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
960
958
|
let t = performance.now(), n = e.frames;
|
|
961
959
|
if (n.lastFrameAt !== null && n.heldGaps.length + n.releasedGaps.length < vt) {
|
|
962
960
|
let r = t - n.lastFrameAt, i = oe(e.elements);
|
|
963
|
-
(i ? n.heldGaps : n.releasedGaps).push(r), i || (
|
|
961
|
+
(i ? n.heldGaps : n.releasedGaps).push(r), i || (se(n, e.elements, r), n.releasedFrames === 1 && de(e.images, e.elements));
|
|
964
962
|
}
|
|
965
|
-
if (n.lastFrameAt = t,
|
|
966
|
-
O = [...e.elements],
|
|
963
|
+
if (n.lastFrameAt = t, B(n, e.elements), t - e.t0Ms > 1e4) {
|
|
964
|
+
O = [...e.elements], H(t, re(e));
|
|
967
965
|
return;
|
|
968
966
|
}
|
|
969
967
|
e.rafId = requestAnimationFrame(L);
|
|
970
968
|
}, ie = (e) => {
|
|
971
969
|
let t = performance.now();
|
|
972
970
|
w += 1;
|
|
973
|
-
let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r =
|
|
971
|
+
let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = _e(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
|
|
974
972
|
for (let t of e) {
|
|
975
973
|
let e = t.getAttribute(m);
|
|
976
974
|
if (e !== null && gt.has(e)) {
|
|
@@ -991,34 +989,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
991
989
|
holdReleasedAtMs: null,
|
|
992
990
|
firstAnimationAtMs: null,
|
|
993
991
|
frames: ae(),
|
|
994
|
-
images:
|
|
995
|
-
morphs:
|
|
992
|
+
images: le(e),
|
|
993
|
+
morphs: Ee(e),
|
|
996
994
|
tripwires: [],
|
|
997
995
|
rafId: null
|
|
998
|
-
},
|
|
999
|
-
},
|
|
996
|
+
}, B(E.frames, E.elements), E.rafId = requestAnimationFrame(L);
|
|
997
|
+
}, R = (e, t) => {
|
|
1000
998
|
let n = 2, r = () => {
|
|
1001
999
|
if (k) return;
|
|
1002
1000
|
if (--n, n > 0) {
|
|
1003
1001
|
requestAnimationFrame(r);
|
|
1004
1002
|
return;
|
|
1005
1003
|
}
|
|
1006
|
-
let i =
|
|
1004
|
+
let i = ye(t, te());
|
|
1007
1005
|
e.landing.residualInlineTransforms = i.residualInlineTransforms, e.landing.offViewportAtRest = i.offViewportAtRest, e.landing.orphanedHolds = i.orphanedHolds;
|
|
1008
1006
|
};
|
|
1009
1007
|
requestAnimationFrame(r);
|
|
1010
|
-
},
|
|
1008
|
+
}, z = (e, t) => {
|
|
1011
1009
|
let n = 2, r = () => {
|
|
1012
1010
|
if (!k) {
|
|
1013
1011
|
if (--n, n > 0) {
|
|
1014
1012
|
requestAnimationFrame(r);
|
|
1015
1013
|
return;
|
|
1016
1014
|
}
|
|
1017
|
-
e.morphs =
|
|
1015
|
+
e.morphs = je(t.morphs, te());
|
|
1018
1016
|
}
|
|
1019
1017
|
};
|
|
1020
1018
|
requestAnimationFrame(r);
|
|
1021
|
-
},
|
|
1019
|
+
}, V = (e, t, n, r) => ({
|
|
1022
1020
|
id: r ? `${e.id} (in flight)` : e.id,
|
|
1023
1021
|
...e.routerId === void 0 ? {} : { routerId: e.routerId },
|
|
1024
1022
|
...e.bucket === null ? {} : { bucket: e.bucket },
|
|
@@ -1032,20 +1030,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1032
1030
|
iso: (/* @__PURE__ */ new Date()).toISOString()
|
|
1033
1031
|
},
|
|
1034
1032
|
durationMs: K(t - e.t0Ms),
|
|
1035
|
-
driver:
|
|
1033
|
+
driver: ge(e.frames.evidence),
|
|
1036
1034
|
participants: e.participants,
|
|
1037
1035
|
holds: {
|
|
1038
1036
|
kind: e.holdKind,
|
|
1039
1037
|
releasedAtMs: e.holdReleasedAtMs
|
|
1040
1038
|
},
|
|
1041
|
-
frameSamples:
|
|
1039
|
+
frameSamples: he(e.frames.heldGaps, e.frames.releasedGaps),
|
|
1042
1040
|
motion: {
|
|
1043
|
-
...
|
|
1041
|
+
...ce(e.frames),
|
|
1044
1042
|
firstAnimationAtMs: e.firstAnimationAtMs
|
|
1045
1043
|
},
|
|
1046
|
-
images:
|
|
1047
|
-
morphs:
|
|
1048
|
-
tripwires: [...e.tripwires, ...
|
|
1044
|
+
images: fe(e.images),
|
|
1045
|
+
morphs: je(e.morphs, !0),
|
|
1046
|
+
tripwires: [...e.tripwires, ...Ae(e.morphs)],
|
|
1049
1047
|
input: I.inputBetween(e.t0Ms, t),
|
|
1050
1048
|
longTasks: [],
|
|
1051
1049
|
holdLongTasks: [],
|
|
@@ -1056,16 +1054,16 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1056
1054
|
orphanedHolds: []
|
|
1057
1055
|
},
|
|
1058
1056
|
anomalies: []
|
|
1059
|
-
}),
|
|
1057
|
+
}), H = (e, t) => {
|
|
1060
1058
|
let i = E;
|
|
1061
1059
|
/* v8 ignore next -- unreachable: both callers hold a flight. sampleFrame
|
|
1062
1060
|
returns at its own top when `current` is null, and evaluate only calls
|
|
1063
1061
|
this inside `if (current && ...)`. The narrowing stays for the type. */
|
|
1064
1062
|
if (!i) return;
|
|
1065
|
-
|
|
1066
|
-
let a =
|
|
1067
|
-
C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (
|
|
1068
|
-
},
|
|
1063
|
+
de(i.images, i.elements), E = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
|
|
1064
|
+
let a = V(i, e, t, !1);
|
|
1065
|
+
C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (R(a, i.elements), z(a, i)), r && console.info(`[flemo devtools] ${a.id} ${a.kind} driver=${a.driver} ${a.durationMs}ms screens=${a.participants.screens}`);
|
|
1066
|
+
}, U = (e) => {
|
|
1069
1067
|
let t = E;
|
|
1070
1068
|
if (!t || !(e.target instanceof Element)) return;
|
|
1071
1069
|
let n = e.target.getAttribute(m);
|
|
@@ -1078,7 +1076,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1078
1076
|
});
|
|
1079
1077
|
}
|
|
1080
1078
|
(n === "false" || n === null) && e.oldValue !== null && gt.has(e.oldValue) && t.holdReleasedAtMs === null && !oe(t.elements) && (t.holdReleasedAtMs = K(performance.now() - t.t0Ms));
|
|
1081
|
-
},
|
|
1079
|
+
}, me = () => {
|
|
1082
1080
|
let e = P();
|
|
1083
1081
|
if (O.length > 0) {
|
|
1084
1082
|
if (e.some((e) => O.includes(e))) return;
|
|
@@ -1089,18 +1087,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1089
1087
|
return;
|
|
1090
1088
|
}
|
|
1091
1089
|
if (E && e.length === 0) {
|
|
1092
|
-
|
|
1090
|
+
H(performance.now(), []);
|
|
1093
1091
|
return;
|
|
1094
1092
|
}
|
|
1095
|
-
if (E) for (let t of e) E.elements.includes(t) || (E.elements.push(t),
|
|
1096
|
-
},
|
|
1093
|
+
if (E) for (let t of e) E.elements.includes(t) || (E.elements.push(t), ue(E.images, E.elements, t.querySelectorAll("img")), E.participants = F(E.elements));
|
|
1094
|
+
}, ve = null, W = null, be = () => {
|
|
1097
1095
|
let e = document.documentElement;
|
|
1098
1096
|
if (!e) return !1;
|
|
1099
1097
|
let t = new MutationObserver((e) => {
|
|
1100
1098
|
if (k) return;
|
|
1101
1099
|
let t = performance.now();
|
|
1102
|
-
for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ?
|
|
1103
|
-
|
|
1100
|
+
for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ? U(n) : E && (n.attributeName === "data-flemo-morph" || n.attributeName === "data-flemo-morph-camera") && n.target instanceof Element && De(E.morphs, n.target) : (E && Oe(E.morphs, n, t), E && n.addedNodes.length > 0 && ue(E.images, E.elements, n.addedNodes));
|
|
1101
|
+
me();
|
|
1104
1102
|
});
|
|
1105
1103
|
try {
|
|
1106
1104
|
t.observe(e, {
|
|
@@ -1119,30 +1117,30 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1119
1117
|
} catch {
|
|
1120
1118
|
return !1;
|
|
1121
1119
|
}
|
|
1122
|
-
return
|
|
1120
|
+
return ve = t, me(), !0;
|
|
1123
1121
|
};
|
|
1124
|
-
if (!
|
|
1122
|
+
if (!be()) {
|
|
1125
1123
|
let e = () => {
|
|
1126
|
-
|
|
1124
|
+
W = null, k || be();
|
|
1127
1125
|
};
|
|
1128
|
-
|
|
1126
|
+
W = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
|
|
1129
1127
|
}
|
|
1130
|
-
let
|
|
1128
|
+
let xe = () => {
|
|
1131
1129
|
document.visibilityState === "hidden" && (M = !0, a && E === null && Ge(C, "3"));
|
|
1132
1130
|
};
|
|
1133
|
-
document.addEventListener("visibilitychange",
|
|
1134
|
-
let
|
|
1135
|
-
N = 0, !k && (E === null && Ge(C, "3"), N = window.setTimeout(
|
|
1131
|
+
document.addEventListener("visibilitychange", xe);
|
|
1132
|
+
let Se = () => {
|
|
1133
|
+
N = 0, !k && (E === null && Ge(C, "3"), N = window.setTimeout(Se, bt));
|
|
1136
1134
|
};
|
|
1137
|
-
a && (N = window.setTimeout(
|
|
1138
|
-
let
|
|
1135
|
+
a && (N = window.setTimeout(Se, bt));
|
|
1136
|
+
let Ce = (e) => {
|
|
1139
1137
|
let t = x.filter((t) => t.startMs + t.durationMs >= e.t0.ms - 120 && t.startMs <= e.t1.ms), n = e.holds.kind === null ? e.t0.ms : e.holds.releasedAtMs === null ? e.t1.ms : e.t0.ms + e.holds.releasedAtMs;
|
|
1140
1138
|
return {
|
|
1141
1139
|
released: t.filter((e) => e.startMs + e.durationMs > n),
|
|
1142
1140
|
held: t.filter((e) => e.startMs + e.durationMs <= n)
|
|
1143
1141
|
};
|
|
1144
|
-
},
|
|
1145
|
-
let t =
|
|
1142
|
+
}, we = (e) => x.filter((t) => t.startMs >= d && !e.some((e) => t.startMs + t.durationMs >= e.t0.ms && t.startMs <= e.t1.ms)), Te = (e) => {
|
|
1143
|
+
let t = Ce(e), n = {
|
|
1146
1144
|
...e,
|
|
1147
1145
|
longTasks: t.released,
|
|
1148
1146
|
holdLongTasks: t.held,
|
|
@@ -1169,12 +1167,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1169
1167
|
morphs: n.morphs,
|
|
1170
1168
|
tripwires: n.tripwires
|
|
1171
1169
|
}), n;
|
|
1172
|
-
},
|
|
1173
|
-
let e = C.map(
|
|
1170
|
+
}, ke = () => {
|
|
1171
|
+
let e = C.map(Te), n = E;
|
|
1174
1172
|
if (!n) return e;
|
|
1175
1173
|
let r = performance.now(), i = r - n.t0Ms > t;
|
|
1176
|
-
return [...e,
|
|
1177
|
-
},
|
|
1174
|
+
return [...e, Te(V(n, r, i ? re(n) : [], !0))];
|
|
1175
|
+
}, Me = (e) => {
|
|
1178
1176
|
let t = /* @__PURE__ */ new Set(), n = 0, r = 0;
|
|
1179
1177
|
for (let i of e) {
|
|
1180
1178
|
n += i.input.trusted, r += i.input.synthetic;
|
|
@@ -1185,16 +1183,16 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1185
1183
|
synthetic: r,
|
|
1186
1184
|
pointerTypes: [...t].sort()
|
|
1187
1185
|
};
|
|
1188
|
-
},
|
|
1186
|
+
}, Ne = () => {
|
|
1189
1187
|
let e = Ve(), t = { ...e };
|
|
1190
1188
|
for (let [n, r] of Object.entries(l)) n in e || (t[`${n} (at attach, since cleared)`] = r);
|
|
1191
|
-
let n = He(t), r = ne(g, I.sawAnimationEvent()), i =
|
|
1189
|
+
let n = He(t), r = ne(g, I.sawAnimationEvent()), i = ke(), a = E, o = it({
|
|
1192
1190
|
environment: r,
|
|
1193
|
-
idleLongTasks:
|
|
1191
|
+
idleLongTasks: we(i),
|
|
1194
1192
|
observedMs: performance.now() - d,
|
|
1195
1193
|
wentHidden: M,
|
|
1196
1194
|
documentHidden: document.visibilityState === "hidden",
|
|
1197
|
-
input:
|
|
1195
|
+
input: Me(i)
|
|
1198
1196
|
});
|
|
1199
1197
|
return {
|
|
1200
1198
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1220,43 +1218,43 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1220
1218
|
flightAnomalies: i.map((e) => e.anomalies)
|
|
1221
1219
|
}),
|
|
1222
1220
|
blindSpots: [...c],
|
|
1223
|
-
judgingProtocol: [...
|
|
1221
|
+
judgingProtocol: [...pe]
|
|
1224
1222
|
};
|
|
1225
|
-
},
|
|
1223
|
+
}, Pe = (e) => (D = e === null || e === "" ? null : e, D), Fe = () => {
|
|
1226
1224
|
if (!k) {
|
|
1227
|
-
if (k = !0,
|
|
1225
|
+
if (k = !0, ve?.disconnect(), W !== null && (document.removeEventListener("DOMContentLoaded", W), W = null), document.removeEventListener("visibilitychange", xe), I.detach(), S?.disconnect(), window.clearTimeout(N), N = 0, E?.rafId != null && cancelAnimationFrame(E.rafId), E = null, j) {
|
|
1228
1226
|
let e = window;
|
|
1229
1227
|
e.flemo?.__flemoDevtools === !0 && delete e.flemo;
|
|
1230
1228
|
}
|
|
1231
1229
|
xt = null;
|
|
1232
1230
|
}
|
|
1233
1231
|
}, G = {
|
|
1234
|
-
detach:
|
|
1235
|
-
report:
|
|
1236
|
-
mark:
|
|
1232
|
+
detach: Fe,
|
|
1233
|
+
report: Ne,
|
|
1234
|
+
mark: Pe
|
|
1237
1235
|
};
|
|
1238
1236
|
if (i) {
|
|
1239
1237
|
let e = window, t = e.flemo;
|
|
1240
1238
|
(t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
|
|
1241
1239
|
__flemoDevtools: !0,
|
|
1242
|
-
report:
|
|
1243
|
-
flights:
|
|
1244
|
-
mark:
|
|
1245
|
-
detach:
|
|
1240
|
+
report: Ne,
|
|
1241
|
+
flights: ke,
|
|
1242
|
+
mark: Pe,
|
|
1243
|
+
detach: Fe
|
|
1246
1244
|
}, j = !0);
|
|
1247
1245
|
}
|
|
1248
1246
|
return xt = G, G;
|
|
1249
|
-
}, wt = O.map((e) => A(d) + j(f, e)).join(","), Tt = () => document.querySelector(wt) !== null, Et = (e) => {
|
|
1247
|
+
}, wt = O.map((e) => A(d) + j(f, e)).join(","), Tt = () => document.querySelector(wt) !== null, Et = "\n:host {\n all: initial;\n color-scheme: dark;\n}\n* { box-sizing: border-box; }\n.root {\n --bg: #14161a;\n --bg-soft: #1b1e24;\n --line: #2b3038;\n --fg: #e6e9ef;\n --fg-dim: #99a1b0;\n --accent: #7cc4ff;\n --warn: #ffb454;\n --bad: #ff6b6b;\n font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n color: var(--fg);\n}\n@media (prefers-color-scheme: light) {\n .root {\n --bg: #ffffff;\n --bg-soft: #f4f6f9;\n --line: #dde1e8;\n --fg: #1a1d22;\n --fg-dim: #5c6472;\n --accent: #0b6bcb;\n --warn: #a35a00;\n --bad: #c2261f;\n }\n}\n", Dt = (e) => {
|
|
1250
1248
|
let t = document.createElement("div");
|
|
1251
1249
|
t.setAttribute(D, ""), t.style.position = "fixed", t.style.top = "0", t.style.left = "0", t.style.width = "0", t.style.height = "0", t.style.zIndex = "2147483000";
|
|
1252
1250
|
let n = t.attachShadow({ mode: "open" }), r = document.createElement("style");
|
|
1253
|
-
r.textContent = e, n.appendChild(r);
|
|
1251
|
+
r.textContent = Et + e, n.appendChild(r);
|
|
1254
1252
|
let i = document.createElement("div");
|
|
1255
1253
|
return i.className = "root", n.appendChild(i), {
|
|
1256
1254
|
host: t,
|
|
1257
1255
|
root: i
|
|
1258
1256
|
};
|
|
1259
|
-
},
|
|
1257
|
+
}, Ot = () => {}, kt = (e) => {
|
|
1260
1258
|
if (e) return {
|
|
1261
1259
|
recorder: e,
|
|
1262
1260
|
ownsRecorder: !1
|
|
@@ -1265,7 +1263,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1265
1263
|
return t?.__flemoDevtools === !0 && typeof t.report == "function" ? {
|
|
1266
1264
|
recorder: {
|
|
1267
1265
|
report: t.report,
|
|
1268
|
-
detach:
|
|
1266
|
+
detach: Ot,
|
|
1269
1267
|
mark: t.mark ?? (() => null)
|
|
1270
1268
|
},
|
|
1271
1269
|
ownsRecorder: !1
|
|
@@ -1273,18 +1271,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1273
1271
|
recorder: Ct(),
|
|
1274
1272
|
ownsRecorder: !0
|
|
1275
1273
|
};
|
|
1276
|
-
},
|
|
1274
|
+
}, At = "http://www.w3.org/2000/svg", q = (e, t, n) => {
|
|
1277
1275
|
let r = document.createElement(e);
|
|
1278
1276
|
return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
|
|
1279
|
-
},
|
|
1280
|
-
let n = document.createElementNS(
|
|
1277
|
+
}, jt = (e, t) => {
|
|
1278
|
+
let n = document.createElementNS(At, e);
|
|
1281
1279
|
for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
|
|
1282
1280
|
return n;
|
|
1283
|
-
},
|
|
1281
|
+
}, Mt = (e) => {
|
|
1284
1282
|
for (; e.firstChild !== null;) e.removeChild(e.firstChild);
|
|
1285
|
-
},
|
|
1283
|
+
}, Nt = (e, t) => {
|
|
1286
1284
|
e.textContent !== t && (e.textContent = t);
|
|
1287
|
-
}, J = (e) => e == null || e === "" ? "—" : String(e), Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—",
|
|
1285
|
+
}, J = (e) => e == null || e === "" ? "—" : String(e), Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Pt = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", Ft = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", It = (e) => {
|
|
1288
1286
|
let t = e?.environment;
|
|
1289
1287
|
if (!t) return "—";
|
|
1290
1288
|
let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
|
|
@@ -1292,14 +1290,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1292
1290
|
J(t.engine),
|
|
1293
1291
|
`dpr ${J(t.devicePixelRatio)}`,
|
|
1294
1292
|
r,
|
|
1295
|
-
`rAF ${
|
|
1293
|
+
`rAF ${Pt(t.rafCadence?.medianGapMs)}`
|
|
1296
1294
|
].join(" · ");
|
|
1297
|
-
},
|
|
1295
|
+
}, Lt = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, Rt = (e) => {
|
|
1298
1296
|
let t = e?.released?.gaps;
|
|
1299
1297
|
if (!Array.isArray(t)) return null;
|
|
1300
1298
|
let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
|
|
1301
1299
|
return n.length >= 2 ? n : null;
|
|
1302
|
-
},
|
|
1300
|
+
}, zt = "\n.toggle {\n position: fixed;\n bottom: 12px;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.toggle:hover { background: var(--bg-soft); }\n.toggle[data-corner=\"bottom-right\"] { right: 12px; }\n.toggle[data-corner=\"bottom-left\"] { left: 12px; }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.count {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bad);\n}\n.dot[hidden] { display: none; }\n.panel {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147482999;\n display: flex;\n flex-direction: column;\n max-width: 100%;\n border-top: 1px solid var(--line);\n background: var(--bg);\n overflow: hidden;\n}\n.panel[hidden] { display: none; }\n.grip {\n flex: 0 0 6px;\n height: 6px;\n background: var(--line);\n cursor: ns-resize;\n touch-action: none;\n}\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--line);\n}\n.env { color: var(--fg-dim); }\n.spacer { flex: 1 1 auto; }\n.act {\n padding: 4px 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n background: var(--bg-soft);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1 1 100%;\n}\n.chips:empty { display: none; }\n.chip {\n padding: 2px 8px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n max-width: 100%;\n overflow-wrap: anywhere;\n}\n/* The verdict reads as prose, not as a tag: it is a sentence about the whole\n session and it is the first thing anybody should read. */\n.chip.lead {\n border-color: var(--fg);\n color: var(--fg);\n white-space: normal;\n max-width: 100%;\n line-height: 1.5;\n}\n.chip.warn { border-color: var(--warn); color: var(--warn); }\n.chip.bad { border-color: var(--bad); color: var(--bad); }\n.body {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n}\n.list {\n flex: 0 0 40%;\n max-width: 340px;\n min-width: 180px;\n overflow: auto;\n border-right: 1px solid var(--line);\n}\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-bottom: 1px solid var(--line);\n background: none;\n color: var(--fg);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.row[aria-selected=\"true\"] { background: var(--bg-soft); }\n.row .kind { font-weight: 700; }\n.row .driver { color: var(--accent); }\n.row .dur, .row .screens { color: var(--fg-dim); }\n.row .n {\n margin-left: auto;\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.row .n.bad { background: var(--bad); color: #fff; }\n.detail { flex: 1 1 auto; overflow: auto; padding: 8px 10px; }\n.section { margin: 0 0 10px; }\n.section > h2 {\n margin: 0 0 4px;\n font: inherit;\n font-weight: 700;\n color: var(--fg-dim);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.kv { display: flex; gap: 8px; }\n.kv > .k { flex: 0 0 34%; max-width: 180px; color: var(--fg-dim); }\n.kv > .v { flex: 1 1 auto; overflow-wrap: anywhere; }\n/* A value that IS the finding — a stall, a re-asserted hold, an orphan. */\n.kv > .v.bad { color: var(--bad); }\n.li { overflow-wrap: anywhere; }\n.li.bad { color: var(--bad); }\n.dim { color: var(--fg-dim); }\n.spark { display: block; width: 100%; height: 28px; }\n.foot { border-top: 1px solid var(--line); padding: 6px 10px; color: var(--fg-dim); }\n.foot summary { cursor: pointer; }\n.foot .li { margin-top: 4px; }\n", Bt = 48, Z = (e, t, n, r) => {
|
|
1303
1301
|
let i = q("div", "kv");
|
|
1304
1302
|
i.appendChild(q("span", "k", t)), i.appendChild(q("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
|
|
1305
1303
|
}, Q = (e, t) => {
|
|
@@ -1307,15 +1305,15 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1307
1305
|
return n.appendChild(q("h2", void 0, t)), e.appendChild(n), n;
|
|
1308
1306
|
}, $ = (e, t, n = "li") => {
|
|
1309
1307
|
e.appendChild(q("div", n, t));
|
|
1310
|
-
},
|
|
1311
|
-
|
|
1308
|
+
}, Vt = (e, t) => {
|
|
1309
|
+
Mt(e);
|
|
1312
1310
|
for (let n of t?.verdict ?? []) e.appendChild(q("span", "chip lead", J(n)));
|
|
1313
1311
|
for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(q("span", "chip bad", `${n.id}: ${J(n.detail)}`));
|
|
1314
1312
|
for (let n of t?.overrides?.warnings ?? []) e.appendChild(q("span", "chip warn", J(n)));
|
|
1315
1313
|
for (let n of t?.anomalies ?? []) e.appendChild(q("span", "chip bad", J(n)));
|
|
1316
1314
|
for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(q("span", "chip", `${n}=${String(r)}`));
|
|
1317
|
-
},
|
|
1318
|
-
if (
|
|
1315
|
+
}, Ht = (e, t, n, r) => {
|
|
1316
|
+
if (Mt(e), t.length === 0) {
|
|
1319
1317
|
$(e, "no flights recorded yet — navigate once", "li dim");
|
|
1320
1318
|
return;
|
|
1321
1319
|
}
|
|
@@ -1325,32 +1323,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1325
1323
|
let c = a?.anomalies?.length ?? 0;
|
|
1326
1324
|
s.appendChild(q("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
|
|
1327
1325
|
}
|
|
1328
|
-
},
|
|
1326
|
+
}, Ut = (e, t, n) => {
|
|
1329
1327
|
if (!n) {
|
|
1330
1328
|
Z(e, t, "—");
|
|
1331
1329
|
return;
|
|
1332
1330
|
}
|
|
1333
1331
|
let r = [
|
|
1334
1332
|
`${X(n.count)} frames`,
|
|
1335
|
-
`median ${
|
|
1336
|
-
`max ${
|
|
1333
|
+
`median ${Pt(n.medianGapMs)}`,
|
|
1334
|
+
`max ${Pt(n.maxGapMs)}`
|
|
1337
1335
|
];
|
|
1338
1336
|
typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
|
|
1339
|
-
},
|
|
1340
|
-
let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a =
|
|
1337
|
+
}, Wt = (e) => {
|
|
1338
|
+
let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a = jt("svg", {
|
|
1341
1339
|
class: "spark",
|
|
1342
1340
|
viewBox: "0 0 100 28",
|
|
1343
1341
|
preserveAspectRatio: "none",
|
|
1344
1342
|
"aria-hidden": "true"
|
|
1345
1343
|
});
|
|
1346
|
-
return a.appendChild(
|
|
1344
|
+
return a.appendChild(jt("polyline", {
|
|
1347
1345
|
points: i,
|
|
1348
1346
|
fill: "none",
|
|
1349
1347
|
stroke: "currentColor",
|
|
1350
1348
|
"stroke-width": "1",
|
|
1351
1349
|
"vector-effect": "non-scaling-stroke"
|
|
1352
1350
|
})), a;
|
|
1353
|
-
},
|
|
1351
|
+
}, Gt = (e, t) => {
|
|
1354
1352
|
let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
|
|
1355
1353
|
if (n.length === 0 && r.length === 0) {
|
|
1356
1354
|
$(e, "none", "li dim");
|
|
@@ -1359,19 +1357,19 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1359
1357
|
let i = (e) => `${Y(e?.startMs)} + ${Y(e?.durationMs)}`;
|
|
1360
1358
|
for (let t of n) $(e, i(t), "li bad");
|
|
1361
1359
|
for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
|
|
1362
|
-
},
|
|
1363
|
-
if (
|
|
1360
|
+
}, Kt = (e, t) => {
|
|
1361
|
+
if (Mt(e), !t) {
|
|
1364
1362
|
$(e, "select a flight", "li dim");
|
|
1365
1363
|
return;
|
|
1366
1364
|
}
|
|
1367
1365
|
let n = Q(e, "timing");
|
|
1368
1366
|
Z(n, "id", J(t.id)), Z(n, "kind / driver", `${J(t.kind)} · ${J(t.driver)}`), Z(n, "router", J(t.routerId)), Z(n, "t0", J(t.t0?.iso)), Z(n, "duration", Y(t.durationMs)), Z(n, "participants", `${X(t.participants?.screens)} screens · ${X(t.participants?.bars)} bars · ${X(t.participants?.decorators)} decorators · ${X(t.participants?.parts)} parts`), Z(n, "hold", `${J(t.holds?.kind)} · released ${Y(t.holds?.releasedAtMs)}`);
|
|
1369
1367
|
let r = Q(e, "frames");
|
|
1370
|
-
|
|
1371
|
-
let i =
|
|
1372
|
-
i && r.appendChild(
|
|
1368
|
+
Ut(r, "held (absorbed)", t.frameSamples?.held), Ut(r, "released (visible)", t.frameSamples?.released);
|
|
1369
|
+
let i = Rt(t.frameSamples);
|
|
1370
|
+
i && r.appendChild(Wt(i));
|
|
1373
1371
|
let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
|
|
1374
|
-
Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", Y(o), (o ?? 0) >=
|
|
1372
|
+
Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", Y(o), (o ?? 0) >= Bt ? "bad" : void 0), Z(a, "paused after release", Ft(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : Y(s), typeof s == "number" ? "bad" : void 0), Z(a, "first animation", t.motion?.firstAnimationAtMs === null || t.motion?.firstAnimationAtMs === void 0 ? "not observed" : `+${Y(t.motion.firstAnimationAtMs)} after t0`);
|
|
1375
1373
|
let c = t.morphs;
|
|
1376
1374
|
if (c) {
|
|
1377
1375
|
let t = Q(e, "shared elements");
|
|
@@ -1379,7 +1377,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1379
1377
|
let n = c.skipped ?? [];
|
|
1380
1378
|
Z(t, "did not fly", n.length === 0 ? "none" : n.join(", "), n.length > 0 ? "bad" : void 0);
|
|
1381
1379
|
let r = c.duplicatedKeys ?? [];
|
|
1382
|
-
r.length > 0 && Z(t, "duplicate keys in one screen", r.join(", "), "bad"), Z(t, "camera",
|
|
1380
|
+
r.length > 0 && Z(t, "duplicate keys in one screen", r.join(", "), "bad"), Z(t, "camera", Ft(c.camera)), Z(t, "ghosts", X(c.ghosts));
|
|
1383
1381
|
let i = (c.strandedRoles ?? 0) + (c.strandedStandIns ?? 0) + (c.strandedGhosts ?? 0) + (c.layerResidue ?? 0) + (c.leakedSheetRules ?? 0);
|
|
1384
1382
|
Z(t, "residue at rest", i === 0 ? "clean" : `${X(c.strandedRoles)} roles · ${X(c.strandedStandIns)} stand-ins · ${X(c.strandedGhosts)} ghosts · ${X(c.layerResidue)} in layer · ${X(c.leakedSheetRules)} rules`, i > 0 ? "bad" : void 0);
|
|
1385
1383
|
}
|
|
@@ -1394,11 +1392,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1394
1392
|
Z(t, "input", `${X(u.trusted)} trusted · ${X(u.synthetic)} synthetic`, u.synthetic > 0 ? "bad" : void 0), Z(t, "pointer types", u.pointerTypes?.join(", ") || "none observed");
|
|
1395
1393
|
}
|
|
1396
1394
|
let d = Q(e, "images"), f = t.images?.completedDuringFlight ?? 0, p = t.images?.heldDuringFlight ?? 0, m = t.images?.completedUnheld, h = typeof m == "number" ? m > 0 : f > p;
|
|
1397
|
-
Z(d, "loading at t0", X(t.images?.loadingAtStart)), Z(d, "added mid-flight", X(t.images?.addedDuringFlight)), Z(d, "completed mid-flight", X(t.images?.completedDuringFlight), h ? "bad" : void 0), Z(d, "held by the engine", X(t.images?.heldDuringFlight)), Z(d, "completed without hold", X(m), h ? "bad" : void 0),
|
|
1395
|
+
Z(d, "loading at t0", X(t.images?.loadingAtStart)), Z(d, "added mid-flight", X(t.images?.addedDuringFlight)), Z(d, "completed mid-flight", X(t.images?.completedDuringFlight), h ? "bad" : void 0), Z(d, "held by the engine", X(t.images?.heldDuringFlight)), Z(d, "completed without hold", X(m), h ? "bad" : void 0), Gt(Q(e, "long tasks"), t);
|
|
1398
1396
|
let g = Q(e, "landing"), _ = t.landing?.residualInlineTransforms ?? [];
|
|
1399
1397
|
if (_.length === 0) Z(g, "inline residue", "clean");
|
|
1400
1398
|
else for (let e of _) Z(g, "inline residue", J(e));
|
|
1401
|
-
Z(g, "off-viewport at rest",
|
|
1399
|
+
Z(g, "off-viewport at rest", Ft(t.landing?.offViewportAtRest));
|
|
1402
1400
|
let v = t.landing?.stuckStatuses ?? [];
|
|
1403
1401
|
Z(g, "stuck statuses", v.length === 0 ? "none" : v.join(", "));
|
|
1404
1402
|
let y = t.landing?.orphanedHolds ?? [];
|
|
@@ -1410,13 +1408,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1410
1408
|
return;
|
|
1411
1409
|
}
|
|
1412
1410
|
for (let e of x) $(b, J(e), "li bad");
|
|
1413
|
-
},
|
|
1414
|
-
|
|
1411
|
+
}, qt = (e, t) => {
|
|
1412
|
+
Mt(e);
|
|
1415
1413
|
for (let n of t ?? []) $(e, J(n));
|
|
1416
|
-
},
|
|
1417
|
-
if (
|
|
1418
|
-
if (typeof document > "u") return { detach:
|
|
1419
|
-
let { recorder: t, ownsRecorder: n } =
|
|
1414
|
+
}, Jt = 320, Yt = 2e3, Xt = 120, Zt = "Copy report JSON", Qt = () => {}, $t = null, en = (e = {}) => {
|
|
1415
|
+
if ($t) return $t;
|
|
1416
|
+
if (typeof document > "u") return { detach: Qt };
|
|
1417
|
+
let { recorder: t, ownsRecorder: n } = kt(e.recorder), { host: r, root: i } = Dt(zt), a = q("button", "toggle");
|
|
1420
1418
|
a.type = "button", a.setAttribute("data-corner", e.position ?? "bottom-right"), a.setAttribute("aria-label", "flemo devtools");
|
|
1421
1419
|
let o = q("span", "count", "0"), s = q("span", "dot");
|
|
1422
1420
|
s.hidden = !0, a.appendChild(q("span", "mark", "flemo")), a.appendChild(o), a.appendChild(s);
|
|
@@ -1424,7 +1422,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1424
1422
|
c.hidden = !0;
|
|
1425
1423
|
let l = q("div", "grip");
|
|
1426
1424
|
l.setAttribute("role", "separator"), l.setAttribute("aria-label", "Resize flemo devtools panel");
|
|
1427
|
-
let u = q("header", "head"), d = q("div", "env", "—"), f = q("button", "act",
|
|
1425
|
+
let u = q("header", "head"), d = q("div", "env", "—"), f = q("button", "act", Zt);
|
|
1428
1426
|
f.type = "button";
|
|
1429
1427
|
let p = q("button", "act", "Close");
|
|
1430
1428
|
p.type = "button";
|
|
@@ -1440,9 +1438,9 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1440
1438
|
x.appendChild(q("summary", void 0, "What this cannot see"));
|
|
1441
1439
|
let S = q("div");
|
|
1442
1440
|
x.appendChild(S), b.appendChild(x), c.appendChild(l), c.appendChild(u), c.appendChild(_), c.appendChild(b), i.appendChild(a), i.appendChild(c);
|
|
1443
|
-
let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e,
|
|
1441
|
+
let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e, Xt), Math.max(Xt, window.innerHeight * .9)), ee = () => {
|
|
1444
1442
|
try {
|
|
1445
|
-
let e = sessionStorage.getItem(
|
|
1443
|
+
let e = sessionStorage.getItem(Me);
|
|
1446
1444
|
if (e === null) return null;
|
|
1447
1445
|
let t = Number.parseFloat(e);
|
|
1448
1446
|
return Number.isFinite(t) ? t : null;
|
|
@@ -1451,7 +1449,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1451
1449
|
}
|
|
1452
1450
|
}, te = (e) => {
|
|
1453
1451
|
try {
|
|
1454
|
-
sessionStorage.setItem(
|
|
1452
|
+
sessionStorage.setItem(Me, String(Math.round(e)));
|
|
1455
1453
|
} catch {}
|
|
1456
1454
|
}, F = P(ee() ?? window.innerHeight * .4);
|
|
1457
1455
|
c.style.height = `${Math.round(F)}px`;
|
|
@@ -1465,20 +1463,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1465
1463
|
e !== T && (T = e, L());
|
|
1466
1464
|
}, re = () => {
|
|
1467
1465
|
let e = I(), t = e?.flights ?? [];
|
|
1468
|
-
|
|
1466
|
+
Nt(o, String(t.length));
|
|
1469
1467
|
let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
|
|
1470
1468
|
if (s.hidden = !n, c.hidden = !w, !w) return;
|
|
1471
|
-
|
|
1469
|
+
Nt(d, It(e));
|
|
1472
1470
|
let r = JSON.stringify([
|
|
1473
1471
|
e?.overrides?.warnings ?? [],
|
|
1474
1472
|
e?.anomalies ?? [],
|
|
1475
1473
|
e?.overrides?.active ?? {}
|
|
1476
1474
|
]);
|
|
1477
|
-
r !== O && (O = r,
|
|
1478
|
-
let i =
|
|
1479
|
-
i !== E && (E = i,
|
|
1475
|
+
r !== O && (O = r, Vt(g, e)), T === null && t.length > 0 && (T = t[t.length - 1]?.id ?? null);
|
|
1476
|
+
let i = Lt(t, T);
|
|
1477
|
+
i !== E && (E = i, Ht(v, t, T, ne));
|
|
1480
1478
|
let a = t.find((e) => e?.id === T) ?? null, l = JSON.stringify(a);
|
|
1481
|
-
l !== D && (D = l,
|
|
1479
|
+
l !== D && (D = l, Kt(y, a)), k || (k = !0, qt(S, e?.blindSpots));
|
|
1482
1480
|
};
|
|
1483
1481
|
function L() {
|
|
1484
1482
|
C || Tt() || re();
|
|
@@ -1487,38 +1485,38 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1487
1485
|
A = 0, L(), ae();
|
|
1488
1486
|
}
|
|
1489
1487
|
function ae() {
|
|
1490
|
-
A = window.setTimeout(ie, w ?
|
|
1488
|
+
A = window.setTimeout(ie, w ? Jt : Yt);
|
|
1491
1489
|
}
|
|
1492
1490
|
let oe = () => {
|
|
1493
1491
|
window.clearTimeout(A), ae();
|
|
1494
|
-
},
|
|
1492
|
+
}, R = (e) => {
|
|
1495
1493
|
w = e, oe(), L();
|
|
1496
1494
|
};
|
|
1497
|
-
a.addEventListener("click", () =>
|
|
1495
|
+
a.addEventListener("click", () => R(!w)), p.addEventListener("click", () => R(!1)), m.addEventListener("click", () => H()), h.addEventListener("click", () => {
|
|
1498
1496
|
M = M + 1 >= N.length ? -1 : M + 1;
|
|
1499
1497
|
let e = M === -1 ? null : N[M];
|
|
1500
|
-
t.mark(e),
|
|
1498
|
+
t.mark(e), Nt(h, `A/B: ${e ?? "off"}`), O = "", L();
|
|
1501
1499
|
});
|
|
1502
|
-
let
|
|
1500
|
+
let se = () => {
|
|
1503
1501
|
if (!C) {
|
|
1504
1502
|
if (Tt()) {
|
|
1505
|
-
window.clearTimeout(j), j = window.setTimeout(
|
|
1503
|
+
window.clearTimeout(j), j = window.setTimeout(se, Jt);
|
|
1506
1504
|
return;
|
|
1507
1505
|
}
|
|
1508
|
-
|
|
1506
|
+
Nt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(z, 1200);
|
|
1509
1507
|
}
|
|
1510
1508
|
};
|
|
1511
|
-
function
|
|
1509
|
+
function z() {
|
|
1512
1510
|
if (Tt()) {
|
|
1513
|
-
j = window.setTimeout(
|
|
1511
|
+
j = window.setTimeout(z, Jt);
|
|
1514
1512
|
return;
|
|
1515
1513
|
}
|
|
1516
|
-
j = 0,
|
|
1514
|
+
j = 0, Nt(f, Zt);
|
|
1517
1515
|
}
|
|
1518
|
-
let
|
|
1516
|
+
let B = (e) => {
|
|
1519
1517
|
if (C) return;
|
|
1520
1518
|
if (Tt()) {
|
|
1521
|
-
window.clearTimeout(j), j = window.setTimeout(() =>
|
|
1519
|
+
window.clearTimeout(j), j = window.setTimeout(() => B(e), Jt);
|
|
1522
1520
|
return;
|
|
1523
1521
|
}
|
|
1524
1522
|
let t = q("textarea");
|
|
@@ -1527,80 +1525,161 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
|
|
|
1527
1525
|
try {
|
|
1528
1526
|
n.execCommand?.("copy");
|
|
1529
1527
|
} catch {}
|
|
1530
|
-
t.remove(),
|
|
1528
|
+
t.remove(), se();
|
|
1531
1529
|
};
|
|
1532
1530
|
f.addEventListener("click", () => {
|
|
1533
1531
|
let e = JSON.stringify(I(), null, 2), t = navigator.clipboard;
|
|
1534
1532
|
if (t && typeof t.writeText == "function") {
|
|
1535
|
-
t.writeText(e).then(
|
|
1533
|
+
t.writeText(e).then(se, () => B(e));
|
|
1536
1534
|
return;
|
|
1537
1535
|
}
|
|
1538
|
-
|
|
1536
|
+
B(e);
|
|
1539
1537
|
});
|
|
1540
|
-
let
|
|
1538
|
+
let ce = (e) => {
|
|
1541
1539
|
F = P(window.innerHeight - e.clientY), c.style.height = `${Math.round(F)}px`;
|
|
1542
|
-
},
|
|
1543
|
-
window.removeEventListener("pointermove",
|
|
1540
|
+
}, V = () => {
|
|
1541
|
+
window.removeEventListener("pointermove", ce), window.removeEventListener("pointerup", V), te(F);
|
|
1544
1542
|
};
|
|
1545
1543
|
l.addEventListener("pointerdown", (e) => {
|
|
1546
|
-
e.preventDefault(), window.addEventListener("pointermove",
|
|
1544
|
+
e.preventDefault(), window.addEventListener("pointermove", ce), window.addEventListener("pointerup", V);
|
|
1547
1545
|
});
|
|
1548
|
-
function
|
|
1549
|
-
C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove",
|
|
1546
|
+
function H() {
|
|
1547
|
+
C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove", ce), window.removeEventListener("pointerup", V), r.remove(), n && t.detach(), $t = null);
|
|
1550
1548
|
}
|
|
1551
1549
|
document.body.appendChild(r), L(), ae();
|
|
1552
|
-
let
|
|
1553
|
-
return
|
|
1554
|
-
},
|
|
1550
|
+
let le = { detach: H };
|
|
1551
|
+
return $t = le, le;
|
|
1552
|
+
}, tn = 500, nn = 450, rn = "flemo:devtools-hud-hidden", an = "\n.dock {\n position: fixed;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 6px;\n max-width: calc(100vw - 16px);\n}\n.dock[data-edge^=\"top\"] {\n top: max(8px, env(safe-area-inset-top));\n /* The control sits nearest the edge the dock is anchored to, whichever that\n is, so it does not MOVE when the readout it hides collapses under it. A\n control that walks across the screen as you use it is one you have to look\n for, and the whole point of it is to be found with a thumb. */\n flex-direction: column-reverse;\n}\n.dock[data-edge^=\"bottom\"] { bottom: max(12px, env(safe-area-inset-bottom)); }\n.dock[data-edge=\"top\"],\n.dock[data-edge=\"bottom\"] {\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n.dock[data-edge$=\"-left\"] {\n left: max(12px, env(safe-area-inset-left));\n align-items: flex-start;\n}\n.dock[data-edge$=\"-right\"] { right: max(12px, env(safe-area-inset-right)); }\n.hud {\n max-width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 10px;\n background: var(--bg);\n color: var(--fg);\n font-weight: 500;\n white-space: pre;\n text-align: left;\n overflow-x: auto;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n /* No transition and no keyframe anywhere in this sheet: the readout must\n never be a moving thing on a screen whose motion is under test. */\n}\n.hud[hidden] { display: none; }\n.hud[data-alarm=\"true\"] { border-color: var(--bad); color: var(--bad); }\n.hud[data-blocked=\"true\"] { border-color: var(--warn); color: var(--warn); }\n/* The panel's toggle, in the opposite corner: same pill, same mark-and-chip,\n so the two controls read as one instrument rather than two. */\n.eye {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n}\n.eye:hover { background: var(--bg-soft); }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.state {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n", on = (e) => Math.round(e * 10) / 10, sn = (e) => {
|
|
1555
1553
|
if (!e) return "flemo no flight yet";
|
|
1556
1554
|
let t = e.frameSamples?.released, n = e.anomalies?.length ?? 0;
|
|
1557
|
-
return `${e.kind} ${Math.round(e.durationMs)}ms gap ${
|
|
1558
|
-
},
|
|
1555
|
+
return `${e.kind} ${Math.round(e.durationMs)}ms gap ${on(t?.maxGapMs ?? 0)} drop ${t?.over30Count ?? 0}` + (n > 0 ? ` !${n}` : " ok") + (e.bucket ? ` [${e.bucket}]` : "");
|
|
1556
|
+
}, cn = (e, t) => {
|
|
1559
1557
|
let n = [], r = (e?.preconditions ?? []).filter((e) => e.status === "violated");
|
|
1560
|
-
if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${
|
|
1558
|
+
if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${on(e?.environment?.rafCadence?.medianGapMs ?? 0)}ms`), n;
|
|
1561
1559
|
let i = t.frameSamples;
|
|
1562
|
-
n.push(`frames n${i?.released?.count ?? 0} med ${
|
|
1560
|
+
n.push(`frames n${i?.released?.count ?? 0} med ${on(i?.released?.medianGapMs ?? 0)} max ${on(i?.released?.maxGapMs ?? 0)}`), n.push(`motion stall ${on(t.motion?.longestStallMs ?? 0)}ms tail ${t.motion?.tailFrames ?? 0} start +${t.motion?.firstAnimationAtMs ?? "?"}ms`), n.push(`hold ${t.holds?.kind ?? "none"} rel ${t.holds?.releasedAtMs ?? "-"}ms task ${t.longTasks?.length ?? 0}`);
|
|
1563
1561
|
let a = t.morphs;
|
|
1564
1562
|
a && (a.pairable.length > 0 || a.flew.length > 0) && n.push(`morph ${a.flew.length} flew` + (a.camera ? " cam" : "") + (a.skipped.length > 0 ? ` SKIPPED ${a.skipped.length} (${a.skipped.join(",")})` : ""));
|
|
1565
1563
|
let o = t.input;
|
|
1566
1564
|
o && n.push(`input ${o.pointerTypes.join("/") || "none"}` + (o.synthetic > 0 ? ` SYNTHETIC ${o.synthetic}` : ""));
|
|
1567
1565
|
for (let e of t.anomalies ?? []) n.push(`! ${e.slice(0, 120)}`);
|
|
1568
1566
|
return n;
|
|
1569
|
-
},
|
|
1570
|
-
|
|
1567
|
+
}, ln = () => {
|
|
1568
|
+
try {
|
|
1569
|
+
return sessionStorage.getItem(rn) === "1";
|
|
1570
|
+
} catch {
|
|
1571
|
+
return !1;
|
|
1572
|
+
}
|
|
1573
|
+
}, un = (e) => {
|
|
1574
|
+
try {
|
|
1575
|
+
sessionStorage.setItem(rn, e ? "1" : "0");
|
|
1576
|
+
} catch {}
|
|
1577
|
+
}, dn = null, fn = (e = {}) => {
|
|
1578
|
+
if (dn) return dn;
|
|
1571
1579
|
if (typeof document > "u") return { detach: () => {} };
|
|
1572
|
-
let { recorder: t, ownsRecorder: n } =
|
|
1573
|
-
|
|
1574
|
-
let
|
|
1580
|
+
let { recorder: t, ownsRecorder: n } = kt(e.recorder), r = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], { host: i, root: a } = Dt(an);
|
|
1581
|
+
i.style.zIndex = "2147482998";
|
|
1582
|
+
let o = document.createElement("div");
|
|
1583
|
+
o.className = "dock", o.setAttribute("data-edge", e.position ?? "bottom-right");
|
|
1584
|
+
let s = document.createElement("div");
|
|
1585
|
+
s.className = "hud", s.setAttribute("role", "status"), s.textContent = "flemo attaching";
|
|
1586
|
+
let c = document.createElement("button");
|
|
1587
|
+
c.className = "eye", c.type = "button";
|
|
1588
|
+
let l = document.createElement("span");
|
|
1589
|
+
l.className = "mark", l.textContent = "hud";
|
|
1590
|
+
let u = document.createElement("span");
|
|
1591
|
+
u.className = "state", c.appendChild(l), c.appendChild(u), o.appendChild(s), o.appendChild(c), a.appendChild(o);
|
|
1592
|
+
let d = !1, f = e.initialExpanded === !0, p = e.initialHidden ?? ln(), m = -1, h = 0, g = 0, _ = !1, v = "", y = () => {
|
|
1575
1593
|
try {
|
|
1576
1594
|
return t.report();
|
|
1577
1595
|
} catch {
|
|
1578
1596
|
return null;
|
|
1579
1597
|
}
|
|
1580
|
-
},
|
|
1581
|
-
if (
|
|
1582
|
-
let e =
|
|
1583
|
-
|
|
1584
|
-
let i = r.join("\n"), a = (e?.preconditions ?? []).some((e) => e.status === "violated"),
|
|
1585
|
-
i !==
|
|
1586
|
-
},
|
|
1587
|
-
|
|
1588
|
-
},
|
|
1589
|
-
|
|
1598
|
+
}, b = () => {
|
|
1599
|
+
if (d || p || Tt()) return;
|
|
1600
|
+
let e = y(), t = e?.flights ?? [], n = t[t.length - 1], r = [sn(n)];
|
|
1601
|
+
f && r.push(...cn(e, n));
|
|
1602
|
+
let i = r.join("\n"), a = (e?.preconditions ?? []).some((e) => e.status === "violated"), o = (n?.anomalies?.length ?? 0) > 0;
|
|
1603
|
+
i !== v && (v = i, s.textContent = i), s.setAttribute("data-alarm", o ? "true" : "false"), s.setAttribute("data-blocked", a ? "true" : "false");
|
|
1604
|
+
}, x = () => {
|
|
1605
|
+
h = 0, b(), h = window.setTimeout(x, tn);
|
|
1606
|
+
}, S = (e) => {
|
|
1607
|
+
p = e, s.hidden = e, u.textContent = e ? "show" : "hide", c.setAttribute("data-hidden", e ? "true" : "false"), c.setAttribute("aria-label", e ? "show the flemo readout" : "hide the flemo readout"), c.setAttribute("aria-expanded", e ? "false" : "true"), window.clearTimeout(h), h = 0, !e && (v = "", b(), h = window.setTimeout(x, tn));
|
|
1608
|
+
}, C = () => {
|
|
1609
|
+
m = m + 1 >= r.length ? -1 : m + 1, t.mark(m === -1 ? null : r[m]), v = "", b();
|
|
1590
1610
|
};
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
},
|
|
1595
|
-
}),
|
|
1596
|
-
window.clearTimeout(
|
|
1597
|
-
}),
|
|
1598
|
-
|
|
1599
|
-
|
|
1611
|
+
s.addEventListener("pointerdown", () => {
|
|
1612
|
+
_ = !1, window.clearTimeout(g), g = window.setTimeout(() => {
|
|
1613
|
+
_ = !0, C();
|
|
1614
|
+
}, nn);
|
|
1615
|
+
}), s.addEventListener("pointerup", () => {
|
|
1616
|
+
window.clearTimeout(g), g = 0, !_ && (f = !f, v = "", b());
|
|
1617
|
+
}), s.addEventListener("pointercancel", () => window.clearTimeout(g)), c.addEventListener("click", () => {
|
|
1618
|
+
S(!p), un(p);
|
|
1619
|
+
});
|
|
1620
|
+
let w = () => {
|
|
1621
|
+
d || (d = !0, window.clearTimeout(h), h = 0, window.clearTimeout(g), g = 0, i.remove(), n && t.detach(), dn = null);
|
|
1600
1622
|
};
|
|
1601
|
-
document.body.appendChild(i),
|
|
1602
|
-
let
|
|
1603
|
-
return
|
|
1623
|
+
document.body.appendChild(i), S(p);
|
|
1624
|
+
let T = { detach: w };
|
|
1625
|
+
return dn = T, T;
|
|
1626
|
+
}, pn = 1200, mn = 2, hn = () => [...document.querySelectorAll(`[${d}]`)], gn = (e) => ve(getComputedStyle(e).transform) ?? 0, _n = (e) => {
|
|
1627
|
+
let t = [];
|
|
1628
|
+
for (let n of e) {
|
|
1629
|
+
let e = n;
|
|
1630
|
+
if (typeof e.getAnimations == "function") for (let n of e.getAnimations()) {
|
|
1631
|
+
let e = n, r = n.currentTime, i = typeof r == "number" ? Math.round(r) : 0;
|
|
1632
|
+
t.push(`${e.animationName ?? "waapi"}|${n.playState}|ct=${i}|rate=${n.playbackRate}`);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return t;
|
|
1636
|
+
}, vn = (e) => e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length, yn = (e) => Math.round(e * 100) / 100, bn = (e) => {
|
|
1637
|
+
/* v8 ignore next -- SSR guard: there is nothing to watch without a document. */
|
|
1638
|
+
if (typeof document > "u") return { detach: () => {} };
|
|
1639
|
+
let t = e.now ?? (() => performance.now()), n = e.schedule ?? ((e) => {
|
|
1640
|
+
requestAnimationFrame(e);
|
|
1641
|
+
}), r = () => {
|
|
1642
|
+
let r = hn();
|
|
1643
|
+
if (r.length === 0) return;
|
|
1644
|
+
let i = Math.max(...r.map((e) => Math.abs(gn(e))));
|
|
1645
|
+
if (i < mn) return;
|
|
1646
|
+
let a = t(), o = [], s = () => {
|
|
1647
|
+
let r = hn();
|
|
1648
|
+
if (o.push({
|
|
1649
|
+
t: Math.round(t() - a),
|
|
1650
|
+
x: r.map((e) => yn(gn(e))),
|
|
1651
|
+
animations: _n(r)
|
|
1652
|
+
}), t() - a < 1200) {
|
|
1653
|
+
n(s);
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
let c = o[0].x, l = 0;
|
|
1657
|
+
for (let [e, t] of c.entries()) Math.abs(t) > Math.abs(c[l]) && (l = e);
|
|
1658
|
+
let u = o.map((e) => e.x[l] ?? 0), d = [];
|
|
1659
|
+
for (let e = 1; e < u.length; e += 1) {
|
|
1660
|
+
let t = Math.abs(u[e] - u[e - 1]);
|
|
1661
|
+
t > 0 && d.push(t);
|
|
1662
|
+
}
|
|
1663
|
+
let f = vn(d.slice(0, 3)), p = vn(d.slice(-3));
|
|
1664
|
+
e.onRelease({
|
|
1665
|
+
samples: o,
|
|
1666
|
+
travelAtReleasePx: yn(i),
|
|
1667
|
+
biggestStepPx: yn(Math.max(0, ...d)),
|
|
1668
|
+
openingStepPx: yn(f),
|
|
1669
|
+
closingStepPx: yn(p),
|
|
1670
|
+
eased: d.length > 3 && p < f * .5,
|
|
1671
|
+
teleported: Math.max(0, ...d) > i * .5
|
|
1672
|
+
});
|
|
1673
|
+
};
|
|
1674
|
+
n(s);
|
|
1675
|
+
}, i = ["pointerup", "pointercancel"];
|
|
1676
|
+
for (let e of i) document.addEventListener(e, r, {
|
|
1677
|
+
capture: !0,
|
|
1678
|
+
passive: !0
|
|
1679
|
+
});
|
|
1680
|
+
return { detach: () => {
|
|
1681
|
+
for (let e of i) document.removeEventListener(e, r, { capture: !0 });
|
|
1682
|
+
} };
|
|
1604
1683
|
};
|
|
1605
1684
|
//#endregion
|
|
1606
|
-
export { c as BLIND_SPOTS,
|
|
1685
|
+
export { c as BLIND_SPOTS, Pe as CORE_FLAGS, Ne as DEVTOOLS_OWNED_FLAGS, Fe as FLAG_REGISTRY, pe as JUDGING_PROTOCOL, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, Me as PANEL_HEIGHT_KEY, mt as REPORT_SCHEMA_VERSION, G as RETIRED_FLAGS, Ie as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, pn as SWIPE_PROBE_MS, Ue as TRACE_KEY, fn as attachDevtoolsHud, en as attachDevtoolsPanel, Ct as attachFlightRecorder, bn as attachSwipeProbe, ne as captureEnvironment, ge as classifyDriver, Ke as clearTrace, he as computeFrameStats, me as computePhaseStats, o as deriveFlightAnomalies, He as deriveOverrideWarnings, it as derivePreconditions, s as deriveReportAnomalies, pt as deriveVerdict, N as detectEngine, F as developmentHints, P as isEmulationSuspected, _e as kindFromStatus, qe as loadTrace, ve as parseTranslateX, ee as sampleRafCadence, Ge as saveTrace, Ve as snapshotOverrides, u as summariseBuckets };
|