@react-perfscope/ui 0.6.0 → 0.7.1

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/dist/index.js CHANGED
@@ -114,6 +114,9 @@ var en = {
114
114
  heapUnsupported: "heap size unavailable (Chromium only)",
115
115
  heapExtensionHint: "Heap size includes browser extensions injected into the page (e.g. React DevTools), so it can rise even while your app is idle. For app-only measurement, record in an incognito window or a profile with extensions disabled.",
116
116
  heapTrendLabel: (cls) => cls === "leak-suspected" ? "leak suspected" : cls === "growing" ? "growing" : "stable",
117
+ leaksTitle: "Suspected leaks",
118
+ leakHint: "Components whose unmounted instances stayed in memory with a count that kept climbing. Shows which component leaks and how many instances \u2014 not what retains them (a heap snapshot, unavailable in-page, is needed for that).",
119
+ leakSuspect: (component, retained, unmounted) => `${component} \u2014 ${retained} retained of ${unmounted} unmounted, climbing`,
117
120
  fpsLabel: "fps",
118
121
  fpsUnsupported: "frame timing unavailable",
119
122
  fpsBadge: (minFps, dropped) => `min ${minFps}fps \xB7 ${dropped} dropped`,
@@ -209,6 +212,9 @@ var ko = {
209
212
  heapUnsupported: "\uD799 \uCE21\uC815 \uBBF8\uC9C0\uC6D0 (\uD06C\uB86C \uC804\uC6A9)",
210
213
  heapExtensionHint: "\uD799 \uD06C\uAE30\uC5D4 \uD398\uC774\uC9C0\uC5D0 \uC8FC\uC785\uB41C \uBE0C\uB77C\uC6B0\uC800 \uD655\uC7A5(\uC608: React DevTools) \uBA54\uBAA8\uB9AC\uB3C4 \uD3EC\uD568\uB3FC\uC694. \uADF8\uB798\uC11C \uC571\uC774 idle\uC774\uC5B4\uB3C4 \uC62C\uB77C\uAC08 \uC218 \uC788\uC5B4\uC694. \uC571\uB9CC \uC815\uD655\uD788 \uC7AC\uB824\uBA74 \uC2DC\uD06C\uB9BF \uCC3D\uC774\uB098 \uD655\uC7A5\uC774 \uAEBC\uC9C4 \uD504\uB85C\uD544\uC5D0\uC11C \uB179\uD654\uD558\uC138\uC694.",
211
214
  heapTrendLabel: (cls) => cls === "leak-suspected" ? "\uB204\uC218 \uC758\uC2EC" : cls === "growing" ? "\uC99D\uAC00 \uC911" : "\uC548\uC815",
215
+ leaksTitle: "\uB204\uC218 \uC758\uC2EC",
216
+ leakHint: "\uC5B8\uB9C8\uC6B4\uD2B8\uB410\uB294\uB370 \uBA54\uBAA8\uB9AC\uC5D0 \uB0A8\uACE0 \uADF8 \uC218\uAC00 \uACC4\uC18D \uB298\uC5B4\uB09C \uCEF4\uD3EC\uB10C\uD2B8\uC608\uC694. \uC5B4\uB5A4 \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uBA87 \uAC1C \uB204\uC218\uD558\uB294\uC9C0\uB294 \uBCF4\uC5EC\uC8FC\uC9C0\uB9CC, \uBB34\uC5C7\uC774 \uBD99\uC7A1\uACE0 \uC788\uB294\uC9C0\uB294(\uD799 \uC2A4\uB0C5\uC0F7\uC774 \uD544\uC694\uD55C\uB370 in-page\uC5D0\uC120 \uBD88\uAC00) \uC54C \uC218 \uC5C6\uC5B4\uC694.",
217
+ leakSuspect: (component, retained, unmounted) => `${component} \u2014 \uC5B8\uB9C8\uC6B4\uD2B8 ${unmounted}\uAC1C \uC911 ${retained}\uAC1C \uBCF4\uC720, \uC99D\uAC00 \uC911`,
212
218
  fpsLabel: "fps",
213
219
  fpsUnsupported: "\uD504\uB808\uC784 \uCE21\uC815 \uBBF8\uC9C0\uC6D0",
214
220
  fpsBadge: (minFps, dropped) => `\uCD5C\uC800 ${minFps}fps \xB7 \uB4DC\uB78D ${dropped}`,
@@ -351,7 +357,7 @@ function Widget(props) {
351
357
  }
352
358
 
353
359
  // src/panel.tsx
354
- import { useState as useState3, useMemo as useMemo3, useEffect, useRef as useRef2 } from "preact/hooks";
360
+ import { useState as useState3, useMemo as useMemo5, useEffect, useRef as useRef2 } from "preact/hooks";
355
361
  import { unsupportedKinds } from "@react-perfscope/core";
356
362
 
357
363
  // src/overlay.ts
@@ -1765,8 +1771,39 @@ function TooltipContent({ s, startedAt }) {
1765
1771
  }
1766
1772
  }
1767
1773
 
1768
- // src/render-insights.tsx
1774
+ // src/leaks.tsx
1769
1775
  import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
1776
+ function LeakList({ suspects }) {
1777
+ const { t } = useI18n();
1778
+ if (!suspects || suspects.length === 0) return null;
1779
+ return /* @__PURE__ */ jsxs4("div", { "data-leaks": "", style: { padding: "8px 10px", borderBottom: "1px solid #1c1c1c" }, children: [
1780
+ /* @__PURE__ */ jsxs4(
1781
+ "div",
1782
+ {
1783
+ style: { display: "flex", alignItems: "center", gap: "6px", marginBottom: "6px" },
1784
+ children: [
1785
+ /* @__PURE__ */ jsx4("span", { style: { color: "#ef4444", fontSize: "11px", fontWeight: 600 }, children: t.leaksTitle }),
1786
+ /* @__PURE__ */ jsxs4("span", { style: { color: "#666", fontSize: "10px" }, children: [
1787
+ "\xD7",
1788
+ suspects.length
1789
+ ] })
1790
+ ]
1791
+ }
1792
+ ),
1793
+ /* @__PURE__ */ jsx4("ul", { style: { listStyle: "none", margin: 0, padding: 0 }, children: suspects.map((s) => /* @__PURE__ */ jsx4(
1794
+ "li",
1795
+ {
1796
+ style: { color: "#e6e6e6", fontSize: "11px", padding: "2px 0", fontVariantNumeric: "tabular-nums" },
1797
+ children: t.leakSuspect(s.component, s.retained, s.unmounted)
1798
+ },
1799
+ s.component
1800
+ )) }),
1801
+ /* @__PURE__ */ jsx4("p", { style: { color: "#666", fontSize: "10px", margin: "6px 0 0", lineHeight: 1.4 }, children: t.leakHint })
1802
+ ] });
1803
+ }
1804
+
1805
+ // src/render-insights.tsx
1806
+ import { jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
1770
1807
  function aggregate(signals) {
1771
1808
  const byName = /* @__PURE__ */ new Map();
1772
1809
  for (const s of signals) {
@@ -1797,7 +1834,7 @@ function RenderInsights({ signals, onSelect }) {
1797
1834
  const top = rows.slice(0, TOP_N);
1798
1835
  const max = top.length > 0 ? top[0].totalMs : 1;
1799
1836
  const hiddenCount = rows.length - top.length;
1800
- return /* @__PURE__ */ jsxs4(
1837
+ return /* @__PURE__ */ jsxs5(
1801
1838
  "div",
1802
1839
  {
1803
1840
  style: {
@@ -1808,12 +1845,12 @@ function RenderInsights({ signals, onSelect }) {
1808
1845
  borderRadius: "8px"
1809
1846
  },
1810
1847
  children: [
1811
- /* @__PURE__ */ jsx4("div", { style: { fontSize: "10px", color: "#888", textTransform: "uppercase", letterSpacing: "0.5px", marginBottom: "6px" }, children: t.topRenderers }),
1812
- /* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "4px" }, children: [
1848
+ /* @__PURE__ */ jsx5("div", { style: { fontSize: "10px", color: "#888", textTransform: "uppercase", letterSpacing: "0.5px", marginBottom: "6px" }, children: t.topRenderers }),
1849
+ /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: "4px" }, children: [
1813
1850
  top.map((a) => {
1814
1851
  const widthPct = max > 0 ? Math.max(2, a.totalMs / max * 100) : 0;
1815
1852
  const color = SEVERITY_COLOR[a.worstSeverity];
1816
- return /* @__PURE__ */ jsxs4(
1853
+ return /* @__PURE__ */ jsxs5(
1817
1854
  "div",
1818
1855
  {
1819
1856
  "data-component": a.component,
@@ -1829,8 +1866,8 @@ function RenderInsights({ signals, onSelect }) {
1829
1866
  },
1830
1867
  title: t.rendererDetail(a.component, a.count, a.totalMs, a.maxMs),
1831
1868
  children: [
1832
- /* @__PURE__ */ jsx4("strong", { style: { flex: "0 0 30%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: a.component }),
1833
- /* @__PURE__ */ jsx4("div", { style: { flex: "1", position: "relative", height: "14px", background: "#1f1f1f", borderRadius: "2px" }, children: /* @__PURE__ */ jsx4(
1869
+ /* @__PURE__ */ jsx5("strong", { style: { flex: "0 0 30%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: a.component }),
1870
+ /* @__PURE__ */ jsx5("div", { style: { flex: "1", position: "relative", height: "14px", background: "#1f1f1f", borderRadius: "2px" }, children: /* @__PURE__ */ jsx5(
1834
1871
  "div",
1835
1872
  {
1836
1873
  style: {
@@ -1845,11 +1882,11 @@ function RenderInsights({ signals, onSelect }) {
1845
1882
  }
1846
1883
  }
1847
1884
  ) }),
1848
- /* @__PURE__ */ jsxs4("span", { style: { flex: "0 0 auto", color, minWidth: "56px", textAlign: "right" }, children: [
1885
+ /* @__PURE__ */ jsxs5("span", { style: { flex: "0 0 auto", color, minWidth: "56px", textAlign: "right" }, children: [
1849
1886
  a.totalMs.toFixed(1),
1850
1887
  "ms"
1851
1888
  ] }),
1852
- /* @__PURE__ */ jsxs4("span", { style: { flex: "0 0 auto", color: "#888", minWidth: "32px", textAlign: "right" }, children: [
1889
+ /* @__PURE__ */ jsxs5("span", { style: { flex: "0 0 auto", color: "#888", minWidth: "32px", textAlign: "right" }, children: [
1853
1890
  "\xD7",
1854
1891
  a.count
1855
1892
  ] })
@@ -1858,7 +1895,7 @@ function RenderInsights({ signals, onSelect }) {
1858
1895
  a.component
1859
1896
  );
1860
1897
  }),
1861
- hiddenCount > 0 && /* @__PURE__ */ jsx4("div", { style: { fontSize: "10px", color: "#666", marginTop: "2px" }, children: t.moreComponents(hiddenCount) })
1898
+ hiddenCount > 0 && /* @__PURE__ */ jsx5("div", { style: { fontSize: "10px", color: "#666", marginTop: "2px" }, children: t.moreComponents(hiddenCount) })
1862
1899
  ] })
1863
1900
  ]
1864
1901
  }
@@ -1866,10 +1903,11 @@ function RenderInsights({ signals, onSelect }) {
1866
1903
  }
1867
1904
 
1868
1905
  // src/inp-episode.tsx
1906
+ import { useMemo as useMemo3 } from "preact/hooks";
1869
1907
  import { correlate } from "@react-perfscope/core";
1870
1908
 
1871
1909
  // src/episode-shared.tsx
1872
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "preact/jsx-runtime";
1910
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
1873
1911
  function memberLabel(m) {
1874
1912
  const s = m.signal;
1875
1913
  if (s.kind === "render") return `${s.component} (${s.reason})`;
@@ -1880,18 +1918,18 @@ function memberLabel(m) {
1880
1918
  return `layout shift ${s.value.toFixed(3)}`;
1881
1919
  }
1882
1920
  function EpisodeMemberRow({ member }) {
1883
- return /* @__PURE__ */ jsxs5(
1921
+ return /* @__PURE__ */ jsxs6(
1884
1922
  "div",
1885
1923
  {
1886
1924
  "data-member-kind": member.signal.kind,
1887
1925
  style: { display: "flex", alignItems: "center", gap: "6px", padding: "1px 0", color: "#ccc" },
1888
1926
  children: [
1889
- /* @__PURE__ */ jsx5("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: memberLabel(member) }),
1890
- member.causedBy && /* @__PURE__ */ jsxs5("span", { style: { flex: "0 0 auto", color: "#888" }, children: [
1927
+ /* @__PURE__ */ jsx6("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: memberLabel(member) }),
1928
+ member.causedBy && /* @__PURE__ */ jsxs6("span", { style: { flex: "0 0 auto", color: "#888" }, children: [
1891
1929
  "\u2190 ",
1892
1930
  member.causedBy.component
1893
1931
  ] }),
1894
- member.confidence === "caused" && /* @__PURE__ */ jsx5(
1932
+ member.confidence === "caused" && /* @__PURE__ */ jsx6(
1895
1933
  "span",
1896
1934
  {
1897
1935
  style: {
@@ -1910,12 +1948,12 @@ function EpisodeMemberRow({ member }) {
1910
1948
  );
1911
1949
  }
1912
1950
  function EpisodeMemberList({ members }) {
1913
- if (members.length === 0) return /* @__PURE__ */ jsx5("span", { style: { color: "#555" }, children: "\u2014" });
1914
- return /* @__PURE__ */ jsx5(Fragment2, { children: members.map((m, i) => /* @__PURE__ */ jsx5(EpisodeMemberRow, { member: m }, i)) });
1951
+ if (members.length === 0) return /* @__PURE__ */ jsx6("span", { style: { color: "#555" }, children: "\u2014" });
1952
+ return /* @__PURE__ */ jsx6(Fragment2, { children: members.map((m, i) => /* @__PURE__ */ jsx6(EpisodeMemberRow, { member: m }, i)) });
1915
1953
  }
1916
1954
 
1917
1955
  // src/inp-episode.tsx
1918
- import { jsx as jsx6, jsxs as jsxs6 } from "preact/jsx-runtime";
1956
+ import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
1919
1957
  var PHASES = [
1920
1958
  { phase: "input-delay", labelKey: "inputDelay" },
1921
1959
  { phase: "processing", labelKey: "processingTime" },
@@ -1936,11 +1974,11 @@ function phaseMs(episode, phase) {
1936
1974
  }
1937
1975
  function InpEpisode({ signals }) {
1938
1976
  const { t } = useI18n();
1939
- const episode = worstInteractionEpisode(signals);
1977
+ const episode = useMemo3(() => worstInteractionEpisode(signals), [signals]);
1940
1978
  if (!episode || episode.anchor.kind !== "interaction") return null;
1941
1979
  const a = episode.anchor;
1942
1980
  const target = a.target ? ` on ${a.target}` : "";
1943
- return /* @__PURE__ */ jsxs6(
1981
+ return /* @__PURE__ */ jsxs7(
1944
1982
  "div",
1945
1983
  {
1946
1984
  "data-inp-episode": true,
@@ -1954,33 +1992,33 @@ function InpEpisode({ signals }) {
1954
1992
  overflow: "hidden"
1955
1993
  },
1956
1994
  children: [
1957
- /* @__PURE__ */ jsxs6("div", { style: { padding: "6px 8px", borderBottom: "1px solid #1f1f1f", color: "#ddd" }, children: [
1958
- /* @__PURE__ */ jsx6("strong", { children: a.eventType }),
1995
+ /* @__PURE__ */ jsxs7("div", { style: { padding: "6px 8px", borderBottom: "1px solid #1f1f1f", color: "#ddd" }, children: [
1996
+ /* @__PURE__ */ jsx7("strong", { children: a.eventType }),
1959
1997
  target,
1960
1998
  " \u2014 ",
1961
- /* @__PURE__ */ jsxs6("strong", { children: [
1999
+ /* @__PURE__ */ jsxs7("strong", { children: [
1962
2000
  Math.round(a.duration),
1963
2001
  "ms"
1964
2002
  ] }),
1965
2003
  " ",
1966
- /* @__PURE__ */ jsx6("span", { style: { color: "#888" }, children: "INP" })
2004
+ /* @__PURE__ */ jsx7("span", { style: { color: "#888" }, children: "INP" })
1967
2005
  ] }),
1968
2006
  PHASES.map(({ phase, labelKey }) => {
1969
2007
  const members = episode.members.filter((m) => m.phase === phase);
1970
- return /* @__PURE__ */ jsxs6(
2008
+ return /* @__PURE__ */ jsxs7(
1971
2009
  "div",
1972
2010
  {
1973
2011
  "data-inp-phase": phase,
1974
2012
  style: { display: "flex", gap: "8px", padding: "5px 8px", borderTop: "1px solid #1a1a1a" },
1975
2013
  children: [
1976
- /* @__PURE__ */ jsxs6("div", { style: { flex: "0 0 92px", color: "#aaa" }, children: [
2014
+ /* @__PURE__ */ jsxs7("div", { style: { flex: "0 0 92px", color: "#aaa" }, children: [
1977
2015
  t[labelKey],
1978
- /* @__PURE__ */ jsxs6("div", { style: { color: "#666", fontSize: "10px" }, children: [
2016
+ /* @__PURE__ */ jsxs7("div", { style: { color: "#666", fontSize: "10px" }, children: [
1979
2017
  Math.round(phaseMs(episode, phase)),
1980
2018
  "ms"
1981
2019
  ] })
1982
2020
  ] }),
1983
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx6(EpisodeMemberList, { members }) })
2021
+ /* @__PURE__ */ jsx7("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx7(EpisodeMemberList, { members }) })
1984
2022
  ]
1985
2023
  },
1986
2024
  phase
@@ -1992,8 +2030,9 @@ function InpEpisode({ signals }) {
1992
2030
  }
1993
2031
 
1994
2032
  // src/long-task-episode.tsx
2033
+ import { useMemo as useMemo4 } from "preact/hooks";
1995
2034
  import { correlate as correlate2 } from "@react-perfscope/core";
1996
- import { jsx as jsx7, jsxs as jsxs7 } from "preact/jsx-runtime";
2035
+ import { jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
1997
2036
  function worstLongTaskEpisode(signals) {
1998
2037
  let worst = null;
1999
2038
  for (const ep of correlate2(signals)) {
@@ -2004,11 +2043,11 @@ function worstLongTaskEpisode(signals) {
2004
2043
  }
2005
2044
  function LongTaskEpisode({ signals }) {
2006
2045
  const { t } = useI18n();
2007
- const episode = worstLongTaskEpisode(signals);
2046
+ const episode = useMemo4(() => worstLongTaskEpisode(signals), [signals]);
2008
2047
  if (!episode || episode.anchor.kind !== "long-task") return null;
2009
2048
  if (episode.members.length === 0) return null;
2010
2049
  const a = episode.anchor;
2011
- return /* @__PURE__ */ jsxs7(
2050
+ return /* @__PURE__ */ jsxs8(
2012
2051
  "div",
2013
2052
  {
2014
2053
  "data-long-task-episode": true,
@@ -2022,15 +2061,15 @@ function LongTaskEpisode({ signals }) {
2022
2061
  overflow: "hidden"
2023
2062
  },
2024
2063
  children: [
2025
- /* @__PURE__ */ jsxs7("div", { style: { padding: "6px 8px", borderBottom: "1px solid #1f1f1f", color: "#ddd" }, children: [
2026
- /* @__PURE__ */ jsx7("strong", { children: t.kindLabel("long-task") }),
2064
+ /* @__PURE__ */ jsxs8("div", { style: { padding: "6px 8px", borderBottom: "1px solid #1f1f1f", color: "#ddd" }, children: [
2065
+ /* @__PURE__ */ jsx8("strong", { children: t.kindLabel("long-task") }),
2027
2066
  " \u2014 ",
2028
- /* @__PURE__ */ jsxs7("strong", { children: [
2067
+ /* @__PURE__ */ jsxs8("strong", { children: [
2029
2068
  Math.round(a.duration),
2030
2069
  "ms"
2031
2070
  ] })
2032
2071
  ] }),
2033
- /* @__PURE__ */ jsx7("div", { style: { padding: "5px 8px" }, children: /* @__PURE__ */ jsx7(EpisodeMemberList, { members: episode.members }) })
2072
+ /* @__PURE__ */ jsx8("div", { style: { padding: "5px 8px" }, children: /* @__PURE__ */ jsx8(EpisodeMemberList, { members: episode.members }) })
2034
2073
  ]
2035
2074
  }
2036
2075
  );
@@ -2076,7 +2115,7 @@ function signalMatchesFilter(signal, query) {
2076
2115
  }
2077
2116
 
2078
2117
  // src/panel.tsx
2079
- import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs8 } from "preact/jsx-runtime";
2118
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
2080
2119
  var RENDER_REASON_COLOR = {
2081
2120
  mount: "#5ac8fa",
2082
2121
  state: "#34c759",
@@ -2100,7 +2139,7 @@ function RenderReasonTag({ reason, changedProps }) {
2100
2139
  const color = RENDER_REASON_COLOR[reason];
2101
2140
  const label = renderReasonLabel(t, reason);
2102
2141
  const keys = reason === "props" && changedProps && changedProps.length > 0 ? `: ${changedProps.join(", ")}` : "";
2103
- return /* @__PURE__ */ jsxs8(
2142
+ return /* @__PURE__ */ jsxs9(
2104
2143
  "span",
2105
2144
  {
2106
2145
  style: {
@@ -2156,7 +2195,7 @@ var WEB_VITAL_UNIT2 = {
2156
2195
  };
2157
2196
  function RatingDot({ rating }) {
2158
2197
  const { t } = useI18n();
2159
- return /* @__PURE__ */ jsx8(
2198
+ return /* @__PURE__ */ jsx9(
2160
2199
  "span",
2161
2200
  {
2162
2201
  "data-rating": rating,
@@ -2214,18 +2253,18 @@ var monoStyle = {
2214
2253
  };
2215
2254
  function LayoutShiftDetail({ s }) {
2216
2255
  const { t } = useI18n();
2217
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2218
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2219
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.value }),
2220
- /* @__PURE__ */ jsx8("span", { children: s.value.toFixed(4) })
2256
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2257
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2258
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.value }),
2259
+ /* @__PURE__ */ jsx9("span", { children: s.value.toFixed(4) })
2221
2260
  ] }),
2222
- s.sources.length === 0 ? /* @__PURE__ */ jsx8("div", { style: { color: "#666" }, children: t.noSourceRects }) : s.sources.map((r, i) => /* @__PURE__ */ jsxs8("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2223
- /* @__PURE__ */ jsxs8("span", { style: { color: "#888" }, children: [
2261
+ s.sources.length === 0 ? /* @__PURE__ */ jsx9("div", { style: { color: "#666" }, children: t.noSourceRects }) : s.sources.map((r, i) => /* @__PURE__ */ jsxs9("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2262
+ /* @__PURE__ */ jsxs9("span", { style: { color: "#888" }, children: [
2224
2263
  t.rect,
2225
2264
  " ",
2226
2265
  i + 1
2227
2266
  ] }),
2228
- /* @__PURE__ */ jsxs8("span", { children: [
2267
+ /* @__PURE__ */ jsxs9("span", { children: [
2229
2268
  "x=",
2230
2269
  r.x.toFixed(0),
2231
2270
  " y=",
@@ -2240,25 +2279,25 @@ function LayoutShiftDetail({ s }) {
2240
2279
  }
2241
2280
  function NetworkDetail({ s }) {
2242
2281
  const { t } = useI18n();
2243
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2244
- /* @__PURE__ */ jsx8("div", { style: { ...detailRowStyle, ...monoStyle, wordBreak: "break-all" }, children: /* @__PURE__ */ jsx8("span", { children: s.url }) }),
2245
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2246
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.started }),
2247
- /* @__PURE__ */ jsxs8("span", { children: [
2282
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2283
+ /* @__PURE__ */ jsx9("div", { style: { ...detailRowStyle, ...monoStyle, wordBreak: "break-all" }, children: /* @__PURE__ */ jsx9("span", { children: s.url }) }),
2284
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2285
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.started }),
2286
+ /* @__PURE__ */ jsxs9("span", { children: [
2248
2287
  s.startedAt.toFixed(0),
2249
2288
  "ms"
2250
2289
  ] })
2251
2290
  ] }),
2252
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2253
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.duration }),
2254
- /* @__PURE__ */ jsxs8("span", { children: [
2291
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2292
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.duration }),
2293
+ /* @__PURE__ */ jsxs9("span", { children: [
2255
2294
  s.duration.toFixed(0),
2256
2295
  "ms"
2257
2296
  ] })
2258
2297
  ] }),
2259
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2260
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.size }),
2261
- /* @__PURE__ */ jsxs8("span", { children: [
2298
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2299
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.size }),
2300
+ /* @__PURE__ */ jsxs9("span", { children: [
2262
2301
  (s.size / 1024).toFixed(2),
2263
2302
  "KB (",
2264
2303
  s.size,
@@ -2267,69 +2306,69 @@ function NetworkDetail({ s }) {
2267
2306
  ")"
2268
2307
  ] })
2269
2308
  ] }),
2270
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2271
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.renderBlocking }),
2272
- /* @__PURE__ */ jsx8("span", { children: s.blocking ? t.yes : t.no })
2309
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2310
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.renderBlocking }),
2311
+ /* @__PURE__ */ jsx9("span", { children: s.blocking ? t.yes : t.no })
2273
2312
  ] })
2274
2313
  ] });
2275
2314
  }
2276
2315
  function WebVitalDetail({ s }) {
2277
2316
  const { t } = useI18n();
2278
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2279
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2280
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.metric }),
2281
- /* @__PURE__ */ jsx8("span", { children: s.name })
2317
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2318
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2319
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.metric }),
2320
+ /* @__PURE__ */ jsx9("span", { children: s.name })
2282
2321
  ] }),
2283
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2284
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.value }),
2285
- /* @__PURE__ */ jsx8("span", { children: s.value.toFixed(2) })
2322
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2323
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.value }),
2324
+ /* @__PURE__ */ jsx9("span", { children: s.value.toFixed(2) })
2286
2325
  ] })
2287
2326
  ] });
2288
2327
  }
2289
2328
  function RenderDetail({ s }) {
2290
2329
  const { t } = useI18n();
2291
2330
  if (s.members && s.members.length > 0) {
2292
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2293
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2294
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.duration }),
2295
- /* @__PURE__ */ jsxs8("span", { children: [
2331
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2332
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2333
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.duration }),
2334
+ /* @__PURE__ */ jsxs9("span", { children: [
2296
2335
  s.duration.toFixed(3),
2297
2336
  "ms"
2298
2337
  ] })
2299
2338
  ] }),
2300
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2301
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.at }),
2302
- /* @__PURE__ */ jsxs8("span", { children: [
2339
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2340
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.at }),
2341
+ /* @__PURE__ */ jsxs9("span", { children: [
2303
2342
  s.at.toFixed(2),
2304
2343
  "ms"
2305
2344
  ] })
2306
2345
  ] }),
2307
- /* @__PURE__ */ jsx8("div", { style: { marginTop: "6px" }, children: /* @__PURE__ */ jsx8(CascadeMembers, { members: s.members }) })
2346
+ /* @__PURE__ */ jsx9("div", { style: { marginTop: "6px" }, children: /* @__PURE__ */ jsx9(CascadeMembers, { members: s.members }) })
2308
2347
  ] });
2309
2348
  }
2310
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2311
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2312
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.component }),
2313
- /* @__PURE__ */ jsx8("span", { children: s.component })
2349
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2350
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2351
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.component }),
2352
+ /* @__PURE__ */ jsx9("span", { children: s.component })
2314
2353
  ] }),
2315
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2316
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.reason }),
2317
- /* @__PURE__ */ jsx8(RenderReasonTag, { reason: s.reason, changedProps: s.changedProps })
2354
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2355
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.reason }),
2356
+ /* @__PURE__ */ jsx9(RenderReasonTag, { reason: s.reason, changedProps: s.changedProps })
2318
2357
  ] }),
2319
- s.reason === "props" && s.changedProps && s.changedProps.length > 0 && /* @__PURE__ */ jsxs8("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2320
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.changedProps }),
2321
- /* @__PURE__ */ jsx8("span", { children: s.changedProps.join(", ") })
2358
+ s.reason === "props" && s.changedProps && s.changedProps.length > 0 && /* @__PURE__ */ jsxs9("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2359
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.changedProps }),
2360
+ /* @__PURE__ */ jsx9("span", { children: s.changedProps.join(", ") })
2322
2361
  ] }),
2323
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2324
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.duration }),
2325
- /* @__PURE__ */ jsxs8("span", { children: [
2362
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2363
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.duration }),
2364
+ /* @__PURE__ */ jsxs9("span", { children: [
2326
2365
  s.duration.toFixed(3),
2327
2366
  "ms"
2328
2367
  ] })
2329
2368
  ] }),
2330
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2331
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.at }),
2332
- /* @__PURE__ */ jsxs8("span", { children: [
2369
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2370
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.at }),
2371
+ /* @__PURE__ */ jsxs9("span", { children: [
2333
2372
  s.at.toFixed(2),
2334
2373
  "ms"
2335
2374
  ] })
@@ -2359,11 +2398,11 @@ function StackFrames({
2359
2398
  cancelled = true;
2360
2399
  };
2361
2400
  }, [raw]);
2362
- return /* @__PURE__ */ jsxs8(Fragment3, { children: [
2363
- resolving && /* @__PURE__ */ jsx8("div", { style: { color: "#666", fontSize: "10px", marginBottom: "4px" }, children: t.resolvingSourceMaps }),
2364
- frames.length === 0 ? /* @__PURE__ */ jsx8("div", { style: { color: "#666" }, children: t.noStack }) : frames.map((f, i) => /* @__PURE__ */ jsxs8("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2365
- f.fnName ? /* @__PURE__ */ jsx8("span", { children: f.fnName }) : /* @__PURE__ */ jsx8("span", { style: { color: "#666" }, children: t.anonymous }),
2366
- /* @__PURE__ */ jsxs8("span", { style: { color: "#888" }, children: [
2401
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
2402
+ resolving && /* @__PURE__ */ jsx9("div", { style: { color: "#666", fontSize: "10px", marginBottom: "4px" }, children: t.resolvingSourceMaps }),
2403
+ frames.length === 0 ? /* @__PURE__ */ jsx9("div", { style: { color: "#666" }, children: t.noStack }) : frames.map((f, i) => /* @__PURE__ */ jsxs9("div", { style: { ...detailRowStyle, ...monoStyle }, children: [
2404
+ f.fnName ? /* @__PURE__ */ jsx9("span", { children: f.fnName }) : /* @__PURE__ */ jsx9("span", { style: { color: "#666" }, children: t.anonymous }),
2405
+ /* @__PURE__ */ jsxs9("span", { style: { color: "#888" }, children: [
2367
2406
  f.file,
2368
2407
  ":",
2369
2408
  f.line,
@@ -2377,7 +2416,7 @@ function ForcedReflowDetail({
2377
2416
  s,
2378
2417
  resolveFrame
2379
2418
  }) {
2380
- return /* @__PURE__ */ jsx8("div", { style: { paddingLeft: "12px" }, children: /* @__PURE__ */ jsx8(StackFrames, { raw: s.stack, resolveFrame }) });
2419
+ return /* @__PURE__ */ jsx9("div", { style: { paddingLeft: "12px" }, children: /* @__PURE__ */ jsx9(StackFrames, { raw: s.stack, resolveFrame }) });
2381
2420
  }
2382
2421
  function HotFunctions({
2383
2422
  attribution,
@@ -2396,26 +2435,26 @@ function HotFunctions({
2396
2435
  cancelled = true;
2397
2436
  };
2398
2437
  }, [attribution]);
2399
- return /* @__PURE__ */ jsxs8("div", { style: { marginTop: "6px" }, children: [
2400
- /* @__PURE__ */ jsx8("div", { style: { ...detailLabelStyle, textTransform: "uppercase", fontSize: "10px", letterSpacing: "0.5px", marginBottom: "1px", color: "#ff9f0a" }, children: t.hotFunctions }),
2401
- /* @__PURE__ */ jsx8("div", { style: { color: "#666", fontSize: "10px", marginBottom: "4px" }, children: t.hotFunctionsHint }),
2438
+ return /* @__PURE__ */ jsxs9("div", { style: { marginTop: "6px" }, children: [
2439
+ /* @__PURE__ */ jsx9("div", { style: { ...detailLabelStyle, textTransform: "uppercase", fontSize: "10px", letterSpacing: "0.5px", marginBottom: "1px", color: "#ff9f0a" }, children: t.hotFunctions }),
2440
+ /* @__PURE__ */ jsx9("div", { style: { color: "#666", fontSize: "10px", marginBottom: "4px" }, children: t.hotFunctionsHint }),
2402
2441
  attribution.map((a, i) => {
2403
2442
  const f = frames[i] ?? a.frame;
2404
2443
  const pct = Math.round(a.selfRatio * 100);
2405
- return /* @__PURE__ */ jsxs8("div", { style: { ...monoStyle, padding: "3px 0", borderTop: i > 0 ? "1px dashed #1f1f1f" : "none" }, children: [
2406
- /* @__PURE__ */ jsxs8("div", { children: [
2407
- /* @__PURE__ */ jsx8("span", { style: { color: "#ff9f0a", fontWeight: 600 }, children: f.fnName || /* @__PURE__ */ jsx8("span", { style: { color: "#666" }, children: t.anonymous }) }),
2408
- /* @__PURE__ */ jsxs8("span", { style: { color: SEVERITY_COLOR.medium, marginLeft: "6px" }, children: [
2444
+ return /* @__PURE__ */ jsxs9("div", { style: { ...monoStyle, padding: "3px 0", borderTop: i > 0 ? "1px dashed #1f1f1f" : "none" }, children: [
2445
+ /* @__PURE__ */ jsxs9("div", { children: [
2446
+ /* @__PURE__ */ jsx9("span", { style: { color: "#ff9f0a", fontWeight: 600 }, children: f.fnName || /* @__PURE__ */ jsx9("span", { style: { color: "#666" }, children: t.anonymous }) }),
2447
+ /* @__PURE__ */ jsxs9("span", { style: { color: SEVERITY_COLOR.medium, marginLeft: "6px" }, children: [
2409
2448
  pct,
2410
2449
  "%"
2411
2450
  ] }),
2412
- /* @__PURE__ */ jsxs8("span", { style: { color: "#666", marginLeft: "6px" }, children: [
2451
+ /* @__PURE__ */ jsxs9("span", { style: { color: "#666", marginLeft: "6px" }, children: [
2413
2452
  "(",
2414
2453
  a.sampleCount,
2415
2454
  ")"
2416
2455
  ] })
2417
2456
  ] }),
2418
- /* @__PURE__ */ jsxs8("div", { style: { color: "#888", wordBreak: "break-all" }, children: [
2457
+ /* @__PURE__ */ jsxs9("div", { style: { color: "#888", wordBreak: "break-all" }, children: [
2419
2458
  f.file,
2420
2459
  ":",
2421
2460
  f.line,
@@ -2432,59 +2471,59 @@ function LongTaskDetail({
2432
2471
  }) {
2433
2472
  const { t } = useI18n();
2434
2473
  const scripts = s.scripts ? [...s.scripts].sort((a, b) => b.duration - a.duration) : [];
2435
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2436
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2437
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.started }),
2438
- /* @__PURE__ */ jsxs8("span", { children: [
2474
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2475
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2476
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.started }),
2477
+ /* @__PURE__ */ jsxs9("span", { children: [
2439
2478
  s.at.toFixed(2),
2440
2479
  "ms"
2441
2480
  ] })
2442
2481
  ] }),
2443
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2444
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.ended }),
2445
- /* @__PURE__ */ jsxs8("span", { children: [
2482
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2483
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.ended }),
2484
+ /* @__PURE__ */ jsxs9("span", { children: [
2446
2485
  (s.at + s.duration).toFixed(2),
2447
2486
  "ms"
2448
2487
  ] })
2449
2488
  ] }),
2450
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2451
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.duration }),
2452
- /* @__PURE__ */ jsxs8("span", { children: [
2489
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2490
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.duration }),
2491
+ /* @__PURE__ */ jsxs9("span", { children: [
2453
2492
  s.duration.toFixed(2),
2454
2493
  "ms"
2455
2494
  ] })
2456
2495
  ] }),
2457
- typeof s.blockingDuration === "number" && /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2458
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.blockingTime }),
2459
- /* @__PURE__ */ jsxs8("span", { children: [
2496
+ typeof s.blockingDuration === "number" && /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2497
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.blockingTime }),
2498
+ /* @__PURE__ */ jsxs9("span", { children: [
2460
2499
  s.blockingDuration.toFixed(2),
2461
2500
  "ms"
2462
2501
  ] })
2463
2502
  ] }),
2464
- s.attribution !== void 0 && s.attribution.length > 0 && /* @__PURE__ */ jsx8(HotFunctions, { attribution: s.attribution, resolveFrame }),
2465
- s.scripts !== void 0 && /* @__PURE__ */ jsxs8("div", { style: { marginTop: "6px" }, children: [
2466
- /* @__PURE__ */ jsx8("div", { style: { ...detailLabelStyle, textTransform: "uppercase", fontSize: "10px", letterSpacing: "0.5px", marginBottom: "4px" }, children: t.scripts }),
2467
- scripts.length === 0 ? /* @__PURE__ */ jsx8("div", { style: { color: "#666" }, children: t.noScripts }) : scripts.map((script, i) => /* @__PURE__ */ jsxs8("div", { style: { ...monoStyle, padding: "3px 0", borderTop: i > 0 ? "1px dashed #1f1f1f" : "none" }, children: [
2468
- /* @__PURE__ */ jsxs8("div", { children: [
2469
- /* @__PURE__ */ jsx8("span", { children: script.sourceFunctionName || /* @__PURE__ */ jsx8("span", { style: { color: "#666" }, children: t.anonymous }) }),
2470
- /* @__PURE__ */ jsx8("span", { style: { color: "#5ac8fa", marginLeft: "6px" }, children: script.invokerType }),
2471
- /* @__PURE__ */ jsxs8("span", { style: { color: SEVERITY_COLOR.medium, marginLeft: "6px" }, children: [
2503
+ s.attribution !== void 0 && s.attribution.length > 0 && /* @__PURE__ */ jsx9(HotFunctions, { attribution: s.attribution, resolveFrame }),
2504
+ s.scripts !== void 0 && /* @__PURE__ */ jsxs9("div", { style: { marginTop: "6px" }, children: [
2505
+ /* @__PURE__ */ jsx9("div", { style: { ...detailLabelStyle, textTransform: "uppercase", fontSize: "10px", letterSpacing: "0.5px", marginBottom: "4px" }, children: t.scripts }),
2506
+ scripts.length === 0 ? /* @__PURE__ */ jsx9("div", { style: { color: "#666" }, children: t.noScripts }) : scripts.map((script, i) => /* @__PURE__ */ jsxs9("div", { style: { ...monoStyle, padding: "3px 0", borderTop: i > 0 ? "1px dashed #1f1f1f" : "none" }, children: [
2507
+ /* @__PURE__ */ jsxs9("div", { children: [
2508
+ /* @__PURE__ */ jsx9("span", { children: script.sourceFunctionName || /* @__PURE__ */ jsx9("span", { style: { color: "#666" }, children: t.anonymous }) }),
2509
+ /* @__PURE__ */ jsx9("span", { style: { color: "#5ac8fa", marginLeft: "6px" }, children: script.invokerType }),
2510
+ /* @__PURE__ */ jsxs9("span", { style: { color: SEVERITY_COLOR.medium, marginLeft: "6px" }, children: [
2472
2511
  script.duration.toFixed(1),
2473
2512
  "ms"
2474
2513
  ] })
2475
2514
  ] }),
2476
- script.sourceURL && /* @__PURE__ */ jsxs8("div", { style: { color: "#888", wordBreak: "break-all" }, children: [
2515
+ script.sourceURL && /* @__PURE__ */ jsxs9("div", { style: { color: "#888", wordBreak: "break-all" }, children: [
2477
2516
  script.sourceURL,
2478
2517
  script.charPosition >= 0 ? `@${script.charPosition}` : ""
2479
2518
  ] }),
2480
- script.invoker && /* @__PURE__ */ jsxs8("div", { style: { color: "#666" }, children: [
2519
+ script.invoker && /* @__PURE__ */ jsxs9("div", { style: { color: "#666" }, children: [
2481
2520
  t.invoker,
2482
2521
  ": ",
2483
2522
  script.invoker
2484
2523
  ] })
2485
2524
  ] }, i))
2486
2525
  ] }),
2487
- s.scripts === void 0 && s.stack.length > 0 && /* @__PURE__ */ jsx8("div", { style: { marginTop: "4px" }, children: /* @__PURE__ */ jsx8(StackFrames, { raw: s.stack, resolveFrame, limit: 5 }) })
2526
+ s.scripts === void 0 && s.stack.length > 0 && /* @__PURE__ */ jsx9("div", { style: { marginTop: "4px" }, children: /* @__PURE__ */ jsx9(StackFrames, { raw: s.stack, resolveFrame, limit: 5 }) })
2488
2527
  ] });
2489
2528
  }
2490
2529
  var INTERACTION_PHASE_COLOR = { input: "#8e8e93", processing: "#5ac8fa", presentation: "#34c759" };
@@ -2499,33 +2538,33 @@ function InteractionDetail({
2499
2538
  { label: t.processingTime, ms: s.processing, color: INTERACTION_PHASE_COLOR.processing },
2500
2539
  { label: t.presentation, ms: s.presentation, color: INTERACTION_PHASE_COLOR.presentation }
2501
2540
  ];
2502
- return /* @__PURE__ */ jsxs8("div", { style: { paddingLeft: "12px" }, children: [
2503
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2504
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.interactionEvent }),
2505
- /* @__PURE__ */ jsxs8("span", { children: [
2541
+ return /* @__PURE__ */ jsxs9("div", { style: { paddingLeft: "12px" }, children: [
2542
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2543
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.interactionEvent }),
2544
+ /* @__PURE__ */ jsxs9("span", { children: [
2506
2545
  s.eventType,
2507
2546
  s.target ? ` \xB7 ${s.target}` : ""
2508
2547
  ] })
2509
2548
  ] }),
2510
- /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2511
- /* @__PURE__ */ jsx8("span", { style: detailLabelStyle, children: t.duration }),
2512
- /* @__PURE__ */ jsxs8("span", { children: [
2549
+ /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2550
+ /* @__PURE__ */ jsx9("span", { style: detailLabelStyle, children: t.duration }),
2551
+ /* @__PURE__ */ jsxs9("span", { children: [
2513
2552
  s.duration.toFixed(0),
2514
2553
  "ms"
2515
2554
  ] })
2516
2555
  ] }),
2517
- /* @__PURE__ */ jsx8("div", { style: { display: "flex", height: "10px", borderRadius: "3px", overflow: "hidden", margin: "5px 0 7px", background: "#1a1a1a" }, children: phases.map((p, i) => /* @__PURE__ */ jsx8("div", { style: { width: `${p.ms / total * 100}%`, background: p.color } }, i)) }),
2518
- phases.map((p, i) => /* @__PURE__ */ jsxs8("div", { style: detailRowStyle, children: [
2519
- /* @__PURE__ */ jsxs8("span", { style: { ...detailLabelStyle, display: "inline-flex", alignItems: "center", gap: "5px" }, children: [
2520
- /* @__PURE__ */ jsx8("span", { style: { width: "7px", height: "7px", borderRadius: "2px", background: p.color, flex: "0 0 7px" } }),
2556
+ /* @__PURE__ */ jsx9("div", { style: { display: "flex", height: "10px", borderRadius: "3px", overflow: "hidden", margin: "5px 0 7px", background: "#1a1a1a" }, children: phases.map((p, i) => /* @__PURE__ */ jsx9("div", { style: { width: `${p.ms / total * 100}%`, background: p.color } }, i)) }),
2557
+ phases.map((p, i) => /* @__PURE__ */ jsxs9("div", { style: detailRowStyle, children: [
2558
+ /* @__PURE__ */ jsxs9("span", { style: { ...detailLabelStyle, display: "inline-flex", alignItems: "center", gap: "5px" }, children: [
2559
+ /* @__PURE__ */ jsx9("span", { style: { width: "7px", height: "7px", borderRadius: "2px", background: p.color, flex: "0 0 7px" } }),
2521
2560
  p.label
2522
2561
  ] }),
2523
- /* @__PURE__ */ jsxs8("span", { children: [
2562
+ /* @__PURE__ */ jsxs9("span", { children: [
2524
2563
  p.ms.toFixed(0),
2525
2564
  "ms"
2526
2565
  ] })
2527
2566
  ] }, i)),
2528
- s.attribution !== void 0 && s.attribution.length > 0 && /* @__PURE__ */ jsx8(HotFunctions, { attribution: s.attribution, resolveFrame })
2567
+ s.attribution !== void 0 && s.attribution.length > 0 && /* @__PURE__ */ jsx9(HotFunctions, { attribution: s.attribution, resolveFrame })
2529
2568
  ] });
2530
2569
  }
2531
2570
  function SignalDetail({
@@ -2534,24 +2573,24 @@ function SignalDetail({
2534
2573
  }) {
2535
2574
  switch (s.kind) {
2536
2575
  case "forced-reflow":
2537
- return /* @__PURE__ */ jsx8(ForcedReflowDetail, { s, resolveFrame });
2576
+ return /* @__PURE__ */ jsx9(ForcedReflowDetail, { s, resolveFrame });
2538
2577
  case "layout-shift":
2539
- return /* @__PURE__ */ jsx8(LayoutShiftDetail, { s });
2578
+ return /* @__PURE__ */ jsx9(LayoutShiftDetail, { s });
2540
2579
  case "long-task":
2541
- return /* @__PURE__ */ jsx8(LongTaskDetail, { s, resolveFrame });
2580
+ return /* @__PURE__ */ jsx9(LongTaskDetail, { s, resolveFrame });
2542
2581
  case "interaction":
2543
- return /* @__PURE__ */ jsx8(InteractionDetail, { s, resolveFrame });
2582
+ return /* @__PURE__ */ jsx9(InteractionDetail, { s, resolveFrame });
2544
2583
  case "network":
2545
- return /* @__PURE__ */ jsx8(NetworkDetail, { s });
2584
+ return /* @__PURE__ */ jsx9(NetworkDetail, { s });
2546
2585
  case "web-vital":
2547
- return /* @__PURE__ */ jsx8(WebVitalDetail, { s });
2586
+ return /* @__PURE__ */ jsx9(WebVitalDetail, { s });
2548
2587
  case "render":
2549
- return /* @__PURE__ */ jsx8(RenderDetail, { s });
2588
+ return /* @__PURE__ */ jsx9(RenderDetail, { s });
2550
2589
  }
2551
2590
  }
2552
2591
  function SeverityDot({ sev, title }) {
2553
2592
  const { t } = useI18n();
2554
- return /* @__PURE__ */ jsx8(
2593
+ return /* @__PURE__ */ jsx9(
2555
2594
  "span",
2556
2595
  {
2557
2596
  "data-severity": sev,
@@ -2574,9 +2613,9 @@ function SummaryLine({ signal }) {
2574
2613
  if (signal.kind === "web-vital") {
2575
2614
  const rating = webVitalRating(signal.name, signal.value);
2576
2615
  const unit = WEB_VITAL_UNIT2[signal.name];
2577
- return /* @__PURE__ */ jsxs8("span", { children: [
2578
- /* @__PURE__ */ jsx8(RatingDot, { rating }),
2579
- /* @__PURE__ */ jsx8("strong", { children: signal.name }),
2616
+ return /* @__PURE__ */ jsxs9("span", { children: [
2617
+ /* @__PURE__ */ jsx9(RatingDot, { rating }),
2618
+ /* @__PURE__ */ jsx9("strong", { children: signal.name }),
2580
2619
  ": ",
2581
2620
  signal.value.toFixed(2),
2582
2621
  unit
@@ -2585,12 +2624,12 @@ function SummaryLine({ signal }) {
2585
2624
  const sev = severityForSignal(signal);
2586
2625
  const color = SEVERITY_COLOR[sev];
2587
2626
  if (signal.kind === "long-task") {
2588
- return /* @__PURE__ */ jsxs8("span", { children: [
2627
+ return /* @__PURE__ */ jsxs9("span", { children: [
2589
2628
  "@ ",
2590
2629
  signal.at.toFixed(1),
2591
2630
  "ms \u2022 duration",
2592
2631
  " ",
2593
- /* @__PURE__ */ jsxs8("span", { style: { color }, children: [
2632
+ /* @__PURE__ */ jsxs9("span", { style: { color }, children: [
2594
2633
  signal.duration.toFixed(1),
2595
2634
  "ms"
2596
2635
  ] })
@@ -2598,59 +2637,59 @@ function SummaryLine({ signal }) {
2598
2637
  }
2599
2638
  if (signal.kind === "forced-reflow") {
2600
2639
  const count = signal.count ?? 1;
2601
- return /* @__PURE__ */ jsxs8("span", { children: [
2640
+ return /* @__PURE__ */ jsxs9("span", { children: [
2602
2641
  "@ ",
2603
2642
  signal.at.toFixed(1),
2604
2643
  "ms \u2022 duration",
2605
2644
  " ",
2606
- /* @__PURE__ */ jsxs8("span", { style: { color }, children: [
2645
+ /* @__PURE__ */ jsxs9("span", { style: { color }, children: [
2607
2646
  signal.duration.toFixed(2),
2608
2647
  "ms"
2609
2648
  ] }),
2610
- count > 1 && /* @__PURE__ */ jsxs8("span", { style: { color: "#888" }, children: [
2649
+ count > 1 && /* @__PURE__ */ jsxs9("span", { style: { color: "#888" }, children: [
2611
2650
  " \u2022 ",
2612
2651
  t.coalescedReads(count)
2613
2652
  ] })
2614
2653
  ] });
2615
2654
  }
2616
2655
  if (signal.kind === "layout-shift") {
2617
- return /* @__PURE__ */ jsxs8("span", { children: [
2656
+ return /* @__PURE__ */ jsxs9("span", { children: [
2618
2657
  "@ ",
2619
2658
  signal.at.toFixed(1),
2620
2659
  "ms \u2022 value",
2621
2660
  " ",
2622
- /* @__PURE__ */ jsx8("span", { style: { color }, children: formatCls(signal.value) }),
2661
+ /* @__PURE__ */ jsx9("span", { style: { color }, children: formatCls(signal.value) }),
2623
2662
  " \u2022 ",
2624
2663
  t.sourceCount(signal.sources.length)
2625
2664
  ] });
2626
2665
  }
2627
2666
  if (signal.kind === "render") {
2628
- return /* @__PURE__ */ jsxs8("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" }, children: [
2629
- /* @__PURE__ */ jsx8("strong", { children: signal.component }),
2630
- /* @__PURE__ */ jsx8(RenderReasonTag, { reason: signal.reason, changedProps: signal.changedProps }),
2631
- /* @__PURE__ */ jsxs8("span", { style: { color }, children: [
2667
+ return /* @__PURE__ */ jsxs9("span", { style: { display: "inline-flex", alignItems: "center", gap: "6px" }, children: [
2668
+ /* @__PURE__ */ jsx9("strong", { children: signal.component }),
2669
+ /* @__PURE__ */ jsx9(RenderReasonTag, { reason: signal.reason, changedProps: signal.changedProps }),
2670
+ /* @__PURE__ */ jsxs9("span", { style: { color }, children: [
2632
2671
  signal.duration.toFixed(2),
2633
2672
  "ms"
2634
2673
  ] }),
2635
- signal.count && signal.count > 1 && /* @__PURE__ */ jsx8("span", { style: { color: "#888" }, children: t.cascadeComponents(signal.count) })
2674
+ signal.count && signal.count > 1 && /* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: t.cascadeComponents(signal.count) })
2636
2675
  ] });
2637
2676
  }
2638
2677
  if (signal.kind === "network") {
2639
2678
  const url = signal.url.length > 60 ? signal.url.slice(0, 57) + "..." : signal.url;
2640
- return /* @__PURE__ */ jsxs8("span", { children: [
2679
+ return /* @__PURE__ */ jsxs9("span", { children: [
2641
2680
  url,
2642
2681
  " \u2022 ",
2643
- /* @__PURE__ */ jsxs8("span", { style: { color }, children: [
2682
+ /* @__PURE__ */ jsxs9("span", { style: { color }, children: [
2644
2683
  signal.duration.toFixed(0),
2645
2684
  "ms"
2646
2685
  ] }),
2647
- signal.blocking && /* @__PURE__ */ jsxs8("span", { style: { color: SEVERITY_COLOR.high }, children: [
2686
+ signal.blocking && /* @__PURE__ */ jsxs9("span", { style: { color: SEVERITY_COLOR.high }, children: [
2648
2687
  " \u2022 ",
2649
2688
  t.blocking
2650
2689
  ] })
2651
2690
  ] });
2652
2691
  }
2653
- return /* @__PURE__ */ jsx8("span", { children: summary(signal) });
2692
+ return /* @__PURE__ */ jsx9("span", { children: summary(signal) });
2654
2693
  }
2655
2694
  function tabSupportsGrouping(kind) {
2656
2695
  return kind === "render" || kind === "forced-reflow";
@@ -2724,7 +2763,7 @@ function groupSignals(signals, mode, kind) {
2724
2763
  function SignalRow({ signal, expanded, onToggleExpand, onHoverGeometry, resolveFrame }) {
2725
2764
  const hasGeometry = signal.kind === "layout-shift" && signal.sources.length > 0;
2726
2765
  const sev = severityForSignal(signal);
2727
- return /* @__PURE__ */ jsxs8(
2766
+ return /* @__PURE__ */ jsxs9(
2728
2767
  "li",
2729
2768
  {
2730
2769
  "aria-expanded": expanded,
@@ -2746,22 +2785,22 @@ function SignalRow({ signal, expanded, onToggleExpand, onHoverGeometry, resolveF
2746
2785
  userSelect: "none"
2747
2786
  },
2748
2787
  children: [
2749
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
2750
- /* @__PURE__ */ jsx8("span", { style: { color: "#888", width: "10px" }, children: expanded ? "\u25BC" : "\u25B6" }),
2751
- /* @__PURE__ */ jsx8(SeverityDot, { sev }),
2752
- /* @__PURE__ */ jsx8(SummaryLine, { signal })
2788
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
2789
+ /* @__PURE__ */ jsx9("span", { style: { color: "#888", width: "10px" }, children: expanded ? "\u25BC" : "\u25B6" }),
2790
+ /* @__PURE__ */ jsx9(SeverityDot, { sev }),
2791
+ /* @__PURE__ */ jsx9(SummaryLine, { signal })
2753
2792
  ] }),
2754
- expanded && /* @__PURE__ */ jsx8("div", { style: { marginTop: "6px", paddingTop: "6px", borderTop: "1px dashed #2a2a2a" }, children: /* @__PURE__ */ jsx8(SignalDetail, { s: signal, resolveFrame }) })
2793
+ expanded && /* @__PURE__ */ jsx9("div", { style: { marginTop: "6px", paddingTop: "6px", borderTop: "1px dashed #2a2a2a" }, children: /* @__PURE__ */ jsx9(SignalDetail, { s: signal, resolveFrame }) })
2755
2794
  ]
2756
2795
  }
2757
2796
  );
2758
2797
  }
2759
2798
  function CascadeMembers({ members }) {
2760
2799
  const minDepth = members.reduce((m, s) => Math.min(m, s.depth), Infinity);
2761
- return /* @__PURE__ */ jsx8("div", { children: members.map((m, i) => {
2800
+ return /* @__PURE__ */ jsx9("div", { children: members.map((m, i) => {
2762
2801
  const indent = (m.depth - minDepth) * 14;
2763
2802
  const isCascade = m.reason === "parent";
2764
- return /* @__PURE__ */ jsxs8(
2803
+ return /* @__PURE__ */ jsxs9(
2765
2804
  "div",
2766
2805
  {
2767
2806
  style: {
@@ -2772,10 +2811,10 @@ function CascadeMembers({ members }) {
2772
2811
  gap: "6px"
2773
2812
  },
2774
2813
  children: [
2775
- /* @__PURE__ */ jsx8("span", { style: { color: isCascade ? RENDER_REASON_COLOR.parent : "#555" }, children: m.depth > minDepth ? "\u2514" : "\u2022" }),
2776
- /* @__PURE__ */ jsx8("strong", { children: m.component }),
2777
- /* @__PURE__ */ jsx8(RenderReasonTag, { reason: m.reason, changedProps: m.changedProps }),
2778
- /* @__PURE__ */ jsxs8("span", { style: { color: "#888" }, children: [
2814
+ /* @__PURE__ */ jsx9("span", { style: { color: isCascade ? RENDER_REASON_COLOR.parent : "#555" }, children: m.depth > minDepth ? "\u2514" : "\u2022" }),
2815
+ /* @__PURE__ */ jsx9("strong", { children: m.component }),
2816
+ /* @__PURE__ */ jsx9(RenderReasonTag, { reason: m.reason, changedProps: m.changedProps }),
2817
+ /* @__PURE__ */ jsxs9("span", { style: { color: "#888" }, children: [
2779
2818
  m.duration.toFixed(2),
2780
2819
  "ms"
2781
2820
  ] })
@@ -2789,7 +2828,7 @@ function LanguageToggle() {
2789
2828
  const { lang, setLang, t } = useI18n();
2790
2829
  const langs = ["en", "ko"];
2791
2830
  const labels = { en: "EN", ko: "\uD55C" };
2792
- return /* @__PURE__ */ jsx8(
2831
+ return /* @__PURE__ */ jsx9(
2793
2832
  "div",
2794
2833
  {
2795
2834
  role: "group",
@@ -2802,7 +2841,7 @@ function LanguageToggle() {
2802
2841
  },
2803
2842
  children: langs.map((l) => {
2804
2843
  const active = lang === l;
2805
- return /* @__PURE__ */ jsx8(
2844
+ return /* @__PURE__ */ jsx9(
2806
2845
  "button",
2807
2846
  {
2808
2847
  type: "button",
@@ -2829,10 +2868,10 @@ function LanguageToggle() {
2829
2868
  function Panel(props) {
2830
2869
  const { result, onClose, position = "bottom-right", resolveFrame } = props;
2831
2870
  const { t } = useI18n();
2832
- const grouped = useMemo3(() => groupByKind(result.signals), [result.signals]);
2871
+ const grouped = useMemo5(() => groupByKind(result.signals), [result.signals]);
2833
2872
  const kindsPresent = KIND_ORDER.filter((k) => grouped[k].length > 0);
2834
- const unsupported = useMemo3(() => unsupportedKinds(), []);
2835
- const hasTimelineSignals = result.signals.some((s) => s.kind !== "web-vital") || (result.heapSamples?.length ?? 0) > 0 || (result.frames?.length ?? 0) > 0;
2873
+ const unsupported = useMemo5(() => unsupportedKinds(), []);
2874
+ const hasTimelineSignals = result.signals.some((s) => s.kind !== "web-vital") || (result.heapSamples?.length ?? 0) > 0 || (result.frames?.length ?? 0) > 0 || (result.leakSuspects?.length ?? 0) > 0;
2836
2875
  const [activeTab, setActiveTab] = useState3(
2837
2876
  kindsPresent[0] ?? "forced-reflow"
2838
2877
  );
@@ -2897,12 +2936,12 @@ function Panel(props) {
2897
2936
  flexDirection: "column",
2898
2937
  overflow: "hidden"
2899
2938
  };
2900
- return /* @__PURE__ */ jsxs8("div", { role: "region", "aria-label": t.panelRegion, style: panelStyle, children: [
2901
- /* @__PURE__ */ jsxs8("header", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "8px" }, children: [
2902
- /* @__PURE__ */ jsx8("strong", { children: "react-perfscope" }),
2903
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", gap: "4px", alignItems: "center" }, children: [
2904
- /* @__PURE__ */ jsx8(LanguageToggle, {}),
2905
- /* @__PURE__ */ jsx8(
2939
+ return /* @__PURE__ */ jsxs9("div", { role: "region", "aria-label": t.panelRegion, style: panelStyle, children: [
2940
+ /* @__PURE__ */ jsxs9("header", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "8px" }, children: [
2941
+ /* @__PURE__ */ jsx9("strong", { children: "react-perfscope" }),
2942
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: "4px", alignItems: "center" }, children: [
2943
+ /* @__PURE__ */ jsx9(LanguageToggle, {}),
2944
+ /* @__PURE__ */ jsx9(
2906
2945
  "button",
2907
2946
  {
2908
2947
  type: "button",
@@ -2921,7 +2960,7 @@ function Panel(props) {
2921
2960
  children: t.save
2922
2961
  }
2923
2962
  ),
2924
- /* @__PURE__ */ jsx8(
2963
+ /* @__PURE__ */ jsx9(
2925
2964
  "button",
2926
2965
  {
2927
2966
  type: "button",
@@ -2933,7 +2972,7 @@ function Panel(props) {
2933
2972
  )
2934
2973
  ] })
2935
2974
  ] }),
2936
- unsupported.length > 0 && /* @__PURE__ */ jsx8(
2975
+ unsupported.length > 0 && /* @__PURE__ */ jsx9(
2937
2976
  "div",
2938
2977
  {
2939
2978
  style: {
@@ -2948,9 +2987,9 @@ function Panel(props) {
2948
2987
  children: t.unsupportedInBrowser(unsupported.map((k) => t.kindLabel(k)).join(", "))
2949
2988
  }
2950
2989
  ),
2951
- kindsPresent.length === 0 && /* @__PURE__ */ jsx8("div", { style: { color: "#888" }, children: t.noSignals }),
2952
- kindsPresent.length > 0 && /* @__PURE__ */ jsxs8(Fragment3, { children: [
2953
- /* @__PURE__ */ jsx8(
2990
+ kindsPresent.length === 0 && /* @__PURE__ */ jsx9("div", { style: { color: "#888" }, children: t.noSignals }),
2991
+ kindsPresent.length > 0 && /* @__PURE__ */ jsxs9(Fragment3, { children: [
2992
+ /* @__PURE__ */ jsx9(
2954
2993
  SummaryHeader,
2955
2994
  {
2956
2995
  signals: result.signals,
@@ -2962,8 +3001,8 @@ function Panel(props) {
2962
3001
  }
2963
3002
  }
2964
3003
  ),
2965
- /* @__PURE__ */ jsxs8("nav", { style: { display: "flex", gap: "4px", flexWrap: "wrap", marginBottom: "8px" }, children: [
2966
- hasTimelineSignals && /* @__PURE__ */ jsx8(
3004
+ /* @__PURE__ */ jsxs9("nav", { style: { display: "flex", gap: "4px", flexWrap: "wrap", marginBottom: "8px" }, children: [
3005
+ hasTimelineSignals && /* @__PURE__ */ jsx9(
2967
3006
  "button",
2968
3007
  {
2969
3008
  type: "button",
@@ -2988,7 +3027,7 @@ function Panel(props) {
2988
3027
  kindsPresent.map((kind) => {
2989
3028
  const worst = worstSeverity(grouped[kind]);
2990
3029
  const active = activeKind === kind;
2991
- return /* @__PURE__ */ jsxs8(
3030
+ return /* @__PURE__ */ jsxs9(
2992
3031
  "button",
2993
3032
  {
2994
3033
  type: "button",
@@ -3011,7 +3050,7 @@ function Panel(props) {
3011
3050
  gap: "6px"
3012
3051
  },
3013
3052
  children: [
3014
- worst !== "low" && /* @__PURE__ */ jsx8(SeverityDot, { sev: worst, title: t.worstLabel(worst) }),
3053
+ worst !== "low" && /* @__PURE__ */ jsx9(SeverityDot, { sev: worst, title: t.worstLabel(worst) }),
3015
3054
  t.kindLabel(kind),
3016
3055
  " ",
3017
3056
  grouped[kind].length
@@ -3021,10 +3060,10 @@ function Panel(props) {
3021
3060
  );
3022
3061
  })
3023
3062
  ] }),
3024
- activeKind && activeTab !== "timeline" && /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "6px", fontSize: "11px", color: "#888", flexWrap: "wrap" }, children: [
3025
- /* @__PURE__ */ jsxs8("label", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
3063
+ activeKind && activeTab !== "timeline" && /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "12px", marginBottom: "6px", fontSize: "11px", color: "#888", flexWrap: "wrap" }, children: [
3064
+ /* @__PURE__ */ jsxs9("label", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
3026
3065
  t.sort,
3027
- /* @__PURE__ */ jsxs8(
3066
+ /* @__PURE__ */ jsxs9(
3028
3067
  "select",
3029
3068
  {
3030
3069
  "aria-label": t.sort,
@@ -3036,15 +3075,15 @@ function Panel(props) {
3036
3075
  },
3037
3076
  style: { background: "#1a1a1a", color: "#e6e6e6", border: "1px solid #2a2a2a", borderRadius: "4px", padding: "2px 6px", fontSize: "11px" },
3038
3077
  children: [
3039
- /* @__PURE__ */ jsx8("option", { value: "chronological", children: t.sortChronological }),
3040
- /* @__PURE__ */ jsx8("option", { value: "severity", children: t.sortSeverity })
3078
+ /* @__PURE__ */ jsx9("option", { value: "chronological", children: t.sortChronological }),
3079
+ /* @__PURE__ */ jsx9("option", { value: "severity", children: t.sortSeverity })
3041
3080
  ]
3042
3081
  }
3043
3082
  )
3044
3083
  ] }),
3045
- tabSupportsGrouping(activeKind) && /* @__PURE__ */ jsxs8("label", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
3084
+ tabSupportsGrouping(activeKind) && /* @__PURE__ */ jsxs9("label", { style: { display: "flex", alignItems: "center", gap: "6px" }, children: [
3046
3085
  t.groupBy,
3047
- /* @__PURE__ */ jsxs8(
3086
+ /* @__PURE__ */ jsxs9(
3048
3087
  "select",
3049
3088
  {
3050
3089
  "aria-label": t.groupBy,
@@ -3056,15 +3095,15 @@ function Panel(props) {
3056
3095
  },
3057
3096
  style: { background: "#1a1a1a", color: "#e6e6e6", border: "1px solid #2a2a2a", borderRadius: "4px", padding: "2px 6px", fontSize: "11px" },
3058
3097
  children: [
3059
- /* @__PURE__ */ jsx8("option", { value: "chronological", children: t.groupChronological }),
3060
- activeKind === "render" && /* @__PURE__ */ jsx8("option", { value: "commit", children: t.groupCommit }),
3061
- activeKind === "render" && /* @__PURE__ */ jsx8("option", { value: "component", children: t.groupComponent }),
3062
- activeKind === "forced-reflow" && /* @__PURE__ */ jsx8("option", { value: "source", children: t.groupSource })
3098
+ /* @__PURE__ */ jsx9("option", { value: "chronological", children: t.groupChronological }),
3099
+ activeKind === "render" && /* @__PURE__ */ jsx9("option", { value: "commit", children: t.groupCommit }),
3100
+ activeKind === "render" && /* @__PURE__ */ jsx9("option", { value: "component", children: t.groupComponent }),
3101
+ activeKind === "forced-reflow" && /* @__PURE__ */ jsx9("option", { value: "source", children: t.groupSource })
3063
3102
  ]
3064
3103
  }
3065
3104
  )
3066
3105
  ] }),
3067
- /* @__PURE__ */ jsx8(
3106
+ /* @__PURE__ */ jsx9(
3068
3107
  "input",
3069
3108
  {
3070
3109
  type: "text",
@@ -3079,23 +3118,26 @@ function Panel(props) {
3079
3118
  }
3080
3119
  )
3081
3120
  ] }),
3082
- activeTab === "timeline" && /* @__PURE__ */ jsx8("div", { style: { flexGrow: 1, overflowY: "auto", paddingTop: "4px", paddingBottom: "24px" }, children: /* @__PURE__ */ jsx8(
3083
- Timeline,
3084
- {
3085
- signals: result.signals,
3086
- duration: result.duration,
3087
- startedAt: result.startedAt,
3088
- heapSamples: result.heapSamples,
3089
- frames: result.frames,
3090
- onJump: (s) => {
3091
- setActiveTab(s.kind);
3092
- const inOrder = grouped[s.kind];
3093
- const idx = inOrder.indexOf(s);
3094
- if (idx >= 0) setExpandedKey(`${s.kind}-${idx}`);
3121
+ activeTab === "timeline" && /* @__PURE__ */ jsxs9("div", { style: { flexGrow: 1, overflowY: "auto", paddingTop: "4px", paddingBottom: "24px" }, children: [
3122
+ /* @__PURE__ */ jsx9(LeakList, { suspects: result.leakSuspects }),
3123
+ /* @__PURE__ */ jsx9(
3124
+ Timeline,
3125
+ {
3126
+ signals: result.signals,
3127
+ duration: result.duration,
3128
+ startedAt: result.startedAt,
3129
+ heapSamples: result.heapSamples,
3130
+ frames: result.frames,
3131
+ onJump: (s) => {
3132
+ setActiveTab(s.kind);
3133
+ const inOrder = grouped[s.kind];
3134
+ const idx = inOrder.indexOf(s);
3135
+ if (idx >= 0) setExpandedKey(`${s.kind}-${idx}`);
3136
+ }
3095
3137
  }
3096
- }
3097
- ) }),
3098
- activeKind === "render" && activeTab !== "timeline" && /* @__PURE__ */ jsx8(
3138
+ )
3139
+ ] }),
3140
+ activeKind === "render" && activeTab !== "timeline" && /* @__PURE__ */ jsx9(
3099
3141
  RenderInsights,
3100
3142
  {
3101
3143
  signals: grouped.render.flatMap((s) => s.kind === "render" ? s.members ?? [s] : []).filter((s) => signalMatchesFilter(s, filterText.render ?? "")),
@@ -3105,8 +3147,8 @@ function Panel(props) {
3105
3147
  }
3106
3148
  }
3107
3149
  ),
3108
- activeKind === "long-task" && activeTab !== "timeline" && /* @__PURE__ */ jsx8(LongTaskEpisode, { signals: result.signals }),
3109
- activeKind === "layout-shift" && activeTab !== "timeline" && /* @__PURE__ */ jsx8(
3150
+ activeKind === "long-task" && activeTab !== "timeline" && /* @__PURE__ */ jsx9(LongTaskEpisode, { signals: result.signals }),
3151
+ activeKind === "layout-shift" && activeTab !== "timeline" && /* @__PURE__ */ jsx9(
3110
3152
  "div",
3111
3153
  {
3112
3154
  style: {
@@ -3121,9 +3163,9 @@ function Panel(props) {
3121
3163
  children: t.layoutShiftHint
3122
3164
  }
3123
3165
  ),
3124
- activeKind === "interaction" && activeTab !== "timeline" && /* @__PURE__ */ jsxs8(Fragment3, { children: [
3125
- /* @__PURE__ */ jsx8(InpEpisode, { signals: result.signals }),
3126
- /* @__PURE__ */ jsx8(
3166
+ activeKind === "interaction" && activeTab !== "timeline" && /* @__PURE__ */ jsxs9(Fragment3, { children: [
3167
+ /* @__PURE__ */ jsx9(InpEpisode, { signals: result.signals }),
3168
+ /* @__PURE__ */ jsx9(
3127
3169
  "div",
3128
3170
  {
3129
3171
  style: {
@@ -3139,7 +3181,7 @@ function Panel(props) {
3139
3181
  }
3140
3182
  )
3141
3183
  ] }),
3142
- /* @__PURE__ */ jsx8("ul", { style: { listStyle: "none", margin: 0, padding: 0, overflowY: "auto", flexGrow: 1, display: activeTab === "timeline" ? "none" : void 0 }, children: activeKind && (() => {
3184
+ /* @__PURE__ */ jsx9("ul", { style: { listStyle: "none", margin: 0, padding: 0, overflowY: "auto", flexGrow: 1, display: activeTab === "timeline" ? "none" : void 0 }, children: activeKind && (() => {
3143
3185
  const filtered = grouped[activeKind].filter(
3144
3186
  (s) => signalMatchesFilter(s, filterText[activeKind] ?? "")
3145
3187
  );
@@ -3149,7 +3191,7 @@ function Panel(props) {
3149
3191
  const currentMode = groupMode[activeKind] ?? "chronological";
3150
3192
  if (currentMode === "chronological") {
3151
3193
  const key2 = `${activeKind}-${gi}`;
3152
- return /* @__PURE__ */ jsx8(
3194
+ return /* @__PURE__ */ jsx9(
3153
3195
  SignalRow,
3154
3196
  {
3155
3197
  signal: g.signals[0],
@@ -3166,7 +3208,7 @@ function Panel(props) {
3166
3208
  const isCascade = activeKind === "render" && currentMode === "commit";
3167
3209
  const renderMembers = g.signals.filter((s) => s.kind === "render");
3168
3210
  const unnecessary = isCascade ? renderMembers.filter((s) => s.reason === "parent").length : 0;
3169
- return /* @__PURE__ */ jsxs8(
3211
+ return /* @__PURE__ */ jsxs9(
3170
3212
  "li",
3171
3213
  {
3172
3214
  "aria-expanded": isOpen,
@@ -3181,34 +3223,34 @@ function Panel(props) {
3181
3223
  userSelect: "none"
3182
3224
  },
3183
3225
  children: [
3184
- /* @__PURE__ */ jsxs8("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
3185
- /* @__PURE__ */ jsx8("span", { style: { color: "#888", width: "10px" }, children: isOpen ? "\u25BC" : "\u25B6" }),
3186
- /* @__PURE__ */ jsxs8("span", { children: [
3187
- /* @__PURE__ */ jsx8("strong", { children: g.label }),
3226
+ /* @__PURE__ */ jsxs9("div", { style: { display: "flex", alignItems: "center", gap: "6px", flexWrap: "wrap" }, children: [
3227
+ /* @__PURE__ */ jsx9("span", { style: { color: "#888", width: "10px" }, children: isOpen ? "\u25BC" : "\u25B6" }),
3228
+ /* @__PURE__ */ jsxs9("span", { children: [
3229
+ /* @__PURE__ */ jsx9("strong", { children: g.label }),
3188
3230
  " \xD7",
3189
3231
  g.count
3190
3232
  ] }),
3191
- isCascade && unnecessary > 0 && /* @__PURE__ */ jsxs8("span", { style: { color: RENDER_REASON_COLOR.parent, fontSize: "10px" }, children: [
3233
+ isCascade && unnecessary > 0 && /* @__PURE__ */ jsxs9("span", { style: { color: RENDER_REASON_COLOR.parent, fontSize: "10px" }, children: [
3192
3234
  "\u26A0 ",
3193
3235
  t.unnecessaryRenders(unnecessary)
3194
3236
  ] })
3195
3237
  ] }),
3196
- isOpen && /* @__PURE__ */ jsx8("div", { style: { marginTop: "6px", paddingTop: "6px", borderTop: "1px dashed #2a2a2a", paddingLeft: "8px" }, children: isCascade ? /* @__PURE__ */ jsx8(CascadeMembers, { members: renderMembers }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
3197
- g.signals.slice(0, 20).map((s, si) => /* @__PURE__ */ jsx8("div", { style: { padding: "2px 0" }, children: /* @__PURE__ */ jsx8(SummaryLine, { signal: s }) }, si)),
3198
- g.signals.length > 20 && /* @__PURE__ */ jsx8("div", { style: { color: "#888", marginTop: "4px" }, children: t.moreItems(g.signals.length - 20) })
3238
+ isOpen && /* @__PURE__ */ jsx9("div", { style: { marginTop: "6px", paddingTop: "6px", borderTop: "1px dashed #2a2a2a", paddingLeft: "8px" }, children: isCascade ? /* @__PURE__ */ jsx9(CascadeMembers, { members: renderMembers }) : /* @__PURE__ */ jsxs9(Fragment3, { children: [
3239
+ g.signals.slice(0, 20).map((s, si) => /* @__PURE__ */ jsx9("div", { style: { padding: "2px 0" }, children: /* @__PURE__ */ jsx9(SummaryLine, { signal: s }) }, si)),
3240
+ g.signals.length > 20 && /* @__PURE__ */ jsx9("div", { style: { color: "#888", marginTop: "4px" }, children: t.moreItems(g.signals.length - 20) })
3199
3241
  ] }) })
3200
3242
  ]
3201
3243
  },
3202
3244
  key
3203
3245
  );
3204
3246
  }) }),
3205
- activeKind && activeTab !== "timeline" && (filterText[activeKind] ?? "").trim() !== "" && grouped[activeKind].length > 0 && grouped[activeKind].every((s) => !signalMatchesFilter(s, filterText[activeKind] ?? "")) && /* @__PURE__ */ jsx8("div", { style: { padding: "12px 8px", fontSize: "11px", color: "#888" }, children: t.filterNoMatches })
3247
+ activeKind && activeTab !== "timeline" && (filterText[activeKind] ?? "").trim() !== "" && grouped[activeKind].length > 0 && grouped[activeKind].every((s) => !signalMatchesFilter(s, filterText[activeKind] ?? "")) && /* @__PURE__ */ jsx9("div", { style: { padding: "12px 8px", fontSize: "11px", color: "#888" }, children: t.filterNoMatches })
3206
3248
  ] })
3207
3249
  ] });
3208
3250
  }
3209
3251
 
3210
3252
  // src/app.tsx
3211
- import { jsx as jsx9, jsxs as jsxs9 } from "preact/jsx-runtime";
3253
+ import { jsx as jsx10, jsxs as jsxs10 } from "preact/jsx-runtime";
3212
3254
  function App(props) {
3213
3255
  const { recorder, position = "bottom-right", resolveFrame, finalize } = props;
3214
3256
  const [recording, setRecording] = useState4(false);
@@ -3223,7 +3265,8 @@ function App(props) {
3223
3265
  return;
3224
3266
  }
3225
3267
  const tick = () => {
3226
- setElapsedMs(performance.now() - startedAtRef.current);
3268
+ const elapsed = performance.now() - startedAtRef.current;
3269
+ setElapsedMs(Math.floor(elapsed / 1e3) * 1e3);
3227
3270
  rafRef.current = requestAnimationFrame(tick);
3228
3271
  };
3229
3272
  rafRef.current = requestAnimationFrame(tick);
@@ -3254,8 +3297,8 @@ function App(props) {
3254
3297
  function onClose() {
3255
3298
  setResult(null);
3256
3299
  }
3257
- return /* @__PURE__ */ jsxs9(I18nProvider, { children: [
3258
- result === null && /* @__PURE__ */ jsx9(
3300
+ return /* @__PURE__ */ jsxs10(I18nProvider, { children: [
3301
+ result === null && /* @__PURE__ */ jsx10(
3259
3302
  Widget,
3260
3303
  {
3261
3304
  recording,
@@ -3264,16 +3307,21 @@ function App(props) {
3264
3307
  position
3265
3308
  }
3266
3309
  ),
3267
- result !== null && /* @__PURE__ */ jsx9(Panel, { result, position, onClose, resolveFrame })
3310
+ result !== null && /* @__PURE__ */ jsx10(Panel, { result, position, onClose, resolveFrame })
3268
3311
  ] });
3269
3312
  }
3270
3313
 
3271
3314
  // src/mount.tsx
3272
- import { jsx as jsx10 } from "preact/jsx-runtime";
3315
+ import { jsx as jsx11 } from "preact/jsx-runtime";
3273
3316
  function mount(opts) {
3274
3317
  const { recorder, position = "bottom-right", host = document.body, resolveFrame, finalize } = opts;
3318
+ if (host.querySelector("[data-perfscope-host]")) {
3319
+ console.warn("[react-perfscope] mount(): a widget is already mounted here \u2014 ignoring this call");
3320
+ return () => {
3321
+ };
3322
+ }
3275
3323
  return mountShadow(
3276
- /* @__PURE__ */ jsx10(App, { recorder, position, resolveFrame, finalize }),
3324
+ /* @__PURE__ */ jsx11(App, { recorder, position, resolveFrame, finalize }),
3277
3325
  { parent: host }
3278
3326
  );
3279
3327
  }