@react-native/debugger-frontend
Version:
Debugger frontend for React Native based on Chrome DevTools
319 lines • 156 kB
JavaScript
import*as e from"../../../services/trace_bounds/trace_bounds.js";import*as t from"../../../core/i18n/i18n.js";import*as i from"../../../models/trace/trace.js";import*as n from"../../../ui/components/helpers/helpers.js";import*as s from"../../../ui/legacy/legacy.js";import*as r from"../../../ui/lit/lit.js";import*as o from"../../../ui/visual_logging/visual_logging.js";import"../../../ui/components/menus/menus.js";import*as a from"../../../core/common/common.js";import*as l from"../../../core/sdk/sdk.js";import*as d from"../../../ui/components/buttons/buttons.js";import*as c from"../../mobile_throttling/mobile_throttling.js";import*as h from"../../../core/platform/platform.js";import"../../../ui/components/icon_button/icon_button.js";import*as g from"../../../models/crux-manager/crux-manager.js";import*as p from"../../../ui/components/render_coordinator/render_coordinator.js";import"../../../ui/components/dialogs/dialogs.js";import*as u from"../../../ui/components/input/input.js";import*as m from"../../../models/bindings/bindings.js";import*as v from"../../../models/trace/helpers/helpers.js";import*as b from"../../../ui/legacy/components/utils/utils.js";import*as f from"../utils/utils.js";import*as y from"./insights/insights.js";import*as w from"../../../ui/legacy/theme_support/theme_support.js";import*as S from"../../../core/root/root.js";import*as x from"../../../models/emulation/emulation.js";import*as k from"../../../models/live-metrics/live-metrics.js";import*as T from"../../../ui/components/legacy_wrapper/legacy_wrapper.js";import"../../../ui/components/markdown_view/markdown_view.js";import*as C from"../../../third_party/marked/marked.js";import"../../../ui/components/request_link_icon/request_link_icon.js";import*as $ from"../../../ui/legacy/components/perf_ui/perf_ui.js";import*as P from"../../../core/host/host.js";function L(e){const t=[e];let i=e;for(;null!==i.child;){const e=i.child;null!==e&&(t.push(e),i=e)}return t}var R=Object.freeze({__proto__:null,Breadcrumbs:class{initialBreadcrumb;activeBreadcrumb;constructor(e){this.initialBreadcrumb={window:e,child:null};let t=this.initialBreadcrumb;for(;null!==t.child;)t=t.child;this.activeBreadcrumb=t}add(e){if(!this.isTraceWindowWithinTraceWindow(e,this.activeBreadcrumb.window))throw new Error("Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow");const t={window:e,child:null};return this.activeBreadcrumb.child=t,this.setActiveBreadcrumb(t,{removeChildBreadcrumbs:!1,updateVisibleWindow:!0}),t}isTraceWindowWithinTraceWindow(e,t){return e.min>=t.min&&e.max<=t.max&&!(e.min===t.min&&e.max===t.max)}setInitialBreadcrumbFromLoadedModifications(e){this.initialBreadcrumb=e;let t=e;for(;null!==t.child;)t=t.child;this.setActiveBreadcrumb(t,{removeChildBreadcrumbs:!1,updateVisibleWindow:!0})}setActiveBreadcrumb(t,i){i.removeChildBreadcrumbs&&(t.child=null),this.activeBreadcrumb=t,e.TraceBounds.BoundsManager.instance().setMiniMapBounds(t.window),i.updateVisibleWindow&&e.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(t.window)}},flattenBreadcrumbs:L}),I={cssText:`.breadcrumbs{display:none;align-items:center;height:29px;padding:3px;overflow:scroll hidden}.breadcrumbs::-webkit-scrollbar{display:none}.breadcrumb{padding:2px 6px;border-radius:4px}.breadcrumb:hover{background-color:var(--sys-color-state-hover-on-subtle)}.range{font-size:12px;white-space:nowrap}.active-breadcrumb{font-weight:bold;color:var(--app-color-active-breadcrumb)}\n/*# sourceURL=${import.meta.resolve("./breadcrumbsUI.css")} */\n`};const M=new CSSStyleSheet;M.replaceSync(I.cssText);const{render:E,html:D}=r,H={activateBreadcrumb:"Activate breadcrumb",removeChildBreadcrumbs:"Remove child breadcrumbs"},F=t.i18n.registerUIStrings("panels/timeline/components/BreadcrumbsUI.ts",H),N=t.i18n.getLocalizedString.bind(void 0,F);class z extends Event{breadcrumb;childBreadcrumbsRemoved;static eventName="breadcrumbactivated";constructor(e,t){super(z.eventName),this.breadcrumb=e,this.childBreadcrumbsRemoved=t}}class O extends HTMLElement{#e=this.attachShadow({mode:"open"});#t=this.#i.bind(this);#n=null;#s=null;connectedCallback(){this.#e.adoptedStyleSheets=[M]}set data(e){this.#n=e.initialBreadcrumb,this.#s=e.activeBreadcrumb,n.ScheduledRender.scheduleRender(this,this.#t)}#r(e){this.#s=e,this.dispatchEvent(new z(e))}#o(){const e=this.#e.querySelector(".breadcrumbs");e&&(e.style.display="flex",requestAnimationFrame((()=>{e.scrollWidth-e.clientWidth>0&&requestAnimationFrame((()=>{e.scrollLeft=e.scrollWidth-e.clientWidth}))})))}#a(e,t){const i=new s.ContextMenu.ContextMenu(e);i.defaultSection().appendItem(N(H.activateBreadcrumb),(()=>{this.dispatchEvent(new z(t))})),i.defaultSection().appendItem(N(H.removeChildBreadcrumbs),(()=>{this.dispatchEvent(new z(t,!0))})),i.show()}#l(e,n){const s=i.Helpers.Timing.microToMilli(e.window.range);return D`
<div class="breadcrumb" @contextmenu=${t=>this.#a(t,e)} @click=${()=>this.#r(e)}
jslog=${o.item("timeline.breadcrumb-select").track({click:!0})}>
<span class="${e===this.#s?"active-breadcrumb":""} range">
${0===n?`Full range (${t.TimeUtilities.preciseMillisToString(s,2)})`:`${t.TimeUtilities.preciseMillisToString(s,2)}`}
</span>
</div>
${null!==e.child?D`
<devtools-icon .data=${{iconName:"chevron-right",color:"var(--icon-default)",width:"16px",height:"16px"}}>`:""}
`}#i(){const e=D`
${null===this.#n?r.nothing:D`<div class="breadcrumbs" jslog=${o.section("breadcrumbs")}>
${L(this.#n).map(((e,t)=>this.#l(e,t)))}
</div>`}
`;E(e,this.#e,{host:this}),this.#n?.child&&this.#o()}}customElements.define("devtools-breadcrumbs-ui",O);var A=Object.freeze({__proto__:null,BreadcrumbActivatedEvent:z,BreadcrumbsUI:O}),_={cssText:`:host{display:flex;align-items:center;max-width:100%;height:20px}devtools-select-menu{min-width:160px;max-width:100%;height:20px}\n/*# sourceURL=${import.meta.resolve("./cpuThrottlingSelector.css")} */\n`};const U=new CSSStyleSheet;U.replaceSync(_.cssText);const{html:B}=r,V={cpu:"CPU: {PH1}",cpuThrottling:"CPU throttling: {PH1}",recommendedThrottling:"{PH1} – recommended",recommendedThrottlingReason:"Consider changing setting to simulate real user environments",calibrate:"Calibrate…",recalibrate:"Recalibrate…",labelCalibratedPresets:"Calibrated presets"},q=t.i18n.registerUIStrings("panels/timeline/components/CPUThrottlingSelector.ts",V),j=t.i18n.getLocalizedString.bind(void 0,q);class W extends HTMLElement{#e=this.attachShadow({mode:"open"});#d;#c=null;#h=[];#g;constructor(){super(),this.#d=l.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingOption(),this.#g=a.Settings.Settings.instance().createSetting("calibrated-cpu-throttling",{},"Global"),this.#p(),this.#i()}set recommendedOption(e){this.#c=e,n.ScheduledRender.scheduleRender(this,this.#i)}connectedCallback(){this.#e.adoptedStyleSheets=[U],l.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener("RateChanged",this.#u,this),this.#g.addChangeListener(this.#m,this),this.#u()}disconnectedCallback(){this.#g.removeChangeListener(this.#m,this),l.CPUThrottlingManager.CPUThrottlingManager.instance().removeEventListener("RateChanged",this.#u,this)}#u(){this.#d=l.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingOption(),n.ScheduledRender.scheduleRender(this,this.#i)}#m(){this.#p(),n.ScheduledRender.scheduleRender(this,this.#i)}#v(e){let t;if("string"==typeof e.itemValue)"low-tier-mobile"===e.itemValue?t=l.CPUThrottlingManager.CalibratedLowTierMobileThrottlingOption:"mid-tier-mobile"===e.itemValue&&(t=l.CPUThrottlingManager.CalibratedMidTierMobileThrottlingOption);else{const i=Number(e.itemValue);t=c.ThrottlingPresets.ThrottlingPresets.cpuThrottlingPresets.find((e=>!e.calibratedDeviceType&&e.rate()===i))}t&&c.ThrottlingManager.throttlingManager().setCPUThrottlingOption(t)}#b(){a.Revealer.reveal(this.#g)}#p(){this.#h=[{name:"",items:c.ThrottlingPresets.ThrottlingPresets.cpuThrottlingPresets.filter((e=>!e.calibratedDeviceType))},{name:j(V.labelCalibratedPresets),items:c.ThrottlingPresets.ThrottlingPresets.cpuThrottlingPresets.filter((e=>e.calibratedDeviceType))}]}#i=()=>{let e;this.#c&&this.#d===l.CPUThrottlingManager.NoThrottlingOption&&(e=B`<devtools-button
title=${j(V.recommendedThrottlingReason)}
.iconName=${"info"}
.variant=${"icon"}
></devtools-button>`);const t=this.#d.title(),i=this.#g.get(),n=i.low||i.mid,s=j(n?V.recalibrate:V.calibrate),a=B`
<devtools-select-menu
@selectmenuselected=${this.#v}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.jslogContext=${"cpu-throttling"}
.buttonTitle=${j(V.cpu,{PH1:t})}
.title=${j(V.cpuThrottling,{PH1:t})}
>
${this.#h.map((e=>B`
<devtools-menu-group .name=${e.name} .title=${e.name}>
${e.items.map((e=>{const t=e===this.#c?j(V.recommendedThrottling,{PH1:e.title()}):e.title(),i=e.rate();return B`
<devtools-menu-item
.value=${e.calibratedDeviceType??i}
.selected=${this.#d===e}
.disabled=${0===i}
.title=${t}
jslog=${o.item(e.jslogContext).track({click:!0})}
>
${t}
</devtools-menu-item>
`}))}
${"Calibrated presets"===e.name?B`<devtools-menu-item
.value=${-1}
.title=${s}
jslog=${o.action("cpu-throttling-selector-calibrate").track({click:!0})}
@click=${this.#b}
>
${s}
</devtools-menu-item>`:r.nothing}
</devtools-menu-group>`))}
</devtools-select-menu>
${e}
`;r.render(a,this.#e,{host:this})}}customElements.define("devtools-cpu-throttling-selector",W);var K=Object.freeze({__proto__:null,CPUThrottlingSelector:W});const G={forcedReflow:"Forced reflow",sIsALikelyPerformanceBottleneck:"{PH1} is a likely performance bottleneck.",idleCallbackExecutionExtended:"Idle callback execution extended beyond deadline by {PH1}",sTookS:"{PH1} took {PH2}.",longTask:"Long task",longInteractionINP:"Long interaction",sIsLikelyPoorPageResponsiveness:"{PH1} is indicating poor page responsiveness.",websocketProtocol:"WebSocket protocol",webSocketBytes:"{PH1} byte(s)",webSocketDataLength:"Data length"},Y=t.i18n.registerUIStrings("panels/timeline/components/DetailsView.ts",G),X=t.i18n.getLocalizedString.bind(void 0,Y);var J=Object.freeze({__proto__:null,buildRowsForWebSocketEvent:function(e,n){const s=[],r=n.Initiators.eventToInitiator.get(e);return r&&i.Types.Events.isWebSocketCreate(r)?(s.push({key:t.i18n.lockedString("URL"),value:r.args.data.url}),r.args.data.websocketProtocol&&s.push({key:X(G.websocketProtocol),value:r.args.data.websocketProtocol})):i.Types.Events.isWebSocketCreate(e)&&(s.push({key:t.i18n.lockedString("URL"),value:e.args.data.url}),e.args.data.websocketProtocol&&s.push({key:X(G.websocketProtocol),value:e.args.data.websocketProtocol})),i.Types.Events.isWebSocketTransfer(e)&&e.args.data.dataLength&&s.push({key:X(G.webSocketDataLength),value:`${X(G.webSocketBytes,{PH1:e.args.data.dataLength})}`}),s},buildWarningElementsForEvent:function(e,n){const r=n.Warnings.perEvent.get(e),o=[];if(!r)return o;for(const n of r){const r=i.Helpers.Timing.microToMilli(i.Types.Timing.Micro(e.dur||0)),a=document.createElement("span");switch(n){case"FORCED_REFLOW":{const e=s.XLink.XLink.create("https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts",X(G.forcedReflow),void 0,void 0,"forced-reflow");a.appendChild(t.i18n.getFormatLocalizedString(Y,G.sIsALikelyPerformanceBottleneck,{PH1:e}));break}case"IDLE_CALLBACK_OVER_TIME":{if(!i.Types.Events.isFireIdleCallback(e))break;const n=t.TimeUtilities.millisToString((r||0)-e.args.data.allottedMilliseconds,!0);a.textContent=X(G.idleCallbackExecutionExtended,{PH1:n});break}case"LONG_TASK":{const e=s.XLink.XLink.create("https://web.dev/optimize-long-tasks/",X(G.longTask),void 0,void 0,"long-tasks");a.appendChild(t.i18n.getFormatLocalizedString(Y,G.sTookS,{PH1:e,PH2:t.TimeUtilities.millisToString(r||0,!0)}));break}case"LONG_INTERACTION":{const e=s.XLink.XLink.create("https://web.dev/inp",X(G.longInteractionINP),void 0,void 0,"long-interaction");a.appendChild(t.i18n.getFormatLocalizedString(Y,G.sIsLikelyPoorPageResponsiveness,{PH1:e}));break}default:h.assertNever(n,`Unhandled warning type ${n}`)}o.push(a)}return o},generateInvalidationsList:function(e){const t={},n=new Set;for(const s of e){n.add(s.args.data.nodeId);let e=s.args.data.reason||"unknown";if("unknown"===e&&i.Types.Events.isScheduleStyleInvalidationTracking(s)&&s.args.data.invalidatedSelectorId)switch(s.args.data.invalidatedSelectorId){case"attribute":e="Attribute",s.args.data.changedAttribute&&(e+=` (${s.args.data.changedAttribute})`);break;case"class":e="Class",s.args.data.changedClass&&(e+=` (${s.args.data.changedClass})`);break;case"id":e="Id",s.args.data.changedId&&(e+=` (${s.args.data.changedId})`)}if("PseudoClass"===e&&i.Types.Events.isStyleRecalcInvalidationTracking(s)&&s.args.data.extraData&&(e+=s.args.data.extraData),"Attribute"===e&&i.Types.Events.isStyleRecalcInvalidationTracking(s)&&s.args.data.extraData&&(e+=` (${s.args.data.extraData})`),"StyleInvalidator"===e)continue;const r=t[e]||[];r.push(s),t[e]=r}return{groupedByReason:t,backendNodeIds:n}}}),Z={cssText:`.list{max-height:200px}.list-item:has(.origin-mapping-row.header){position:sticky;top:0;z-index:1;background-color:var(--sys-color-cdt-base-container)}.origin-mapping-row{display:flex;flex-direction:row;width:100%;height:30px}.origin-mapping-row.header{font-weight:var(--ref-typeface-weight-medium);border-bottom:1px solid var(--sys-color-divider)}.origin-mapping-cell{flex:1;display:flex;align-items:center;padding:4px;border-right:1px solid var(--sys-color-divider)}.origin-warning-icon{width:16px;height:16px;margin-right:4px;color:var(--icon-warning)}.origin{text-overflow:ellipsis;overflow-x:hidden}.origin-mapping-cell:last-child{border:none}.origin-mapping-editor{display:flex;flex-direction:row;width:100%;padding:12px 8px;gap:12px}.origin-mapping-editor label{flex:1;font-weight:var(--ref-typeface-weight-medium)}.origin-mapping-editor input{margin-top:4px;width:100%}\n/*# sourceURL=${import.meta.resolve("./originMap.css")} */\n`};const{html:Q}=r,ee={developmentOrigin:"Development origin",productionOrigin:"Production origin",invalidOrigin:'"{PH1}" is not a valid origin or URL.',alreadyMapped:'"{PH1}" is already mapped to a production origin.',pageHasNoData:"The Chrome UX Report does not have sufficient real user data for this page."},te=t.i18n.registerUIStrings("panels/timeline/components/OriginMap.ts",ee),ie=t.i18n.getLocalizedString.bind(void 0,te),ne="developmentOrigin",se="productionOrigin";class re extends s.Widget.WidgetElement{#f;#y;constructor(){super(),this.#f=new s.ListWidget.ListWidget(this,!1,!0),g.CrUXManager.instance().getConfigSetting().addChangeListener(this.#w,this),this.#w()}createWidget(){const e=new s.Widget.Widget(!1,!1,this);return this.#f.registerRequiredCSS(Z),this.#f.show(e.contentElement),e}#S(){return g.CrUXManager.instance().getConfigSetting().get().originMappings||[]}#x(e){const t=g.CrUXManager.instance().getConfigSetting(),i={...t.get()};i.originMappings=e,t.set(i)}#w(){const e=this.#S();this.#f.clear(),this.#f.appendItem({developmentOrigin:ie(ee.developmentOrigin),productionOrigin:ie(ee.productionOrigin),isTitleRow:!0},!1);for(const t of e)this.#f.appendItem(t,!0)}#k(e){try{return new URL(e).origin}catch{return null}}#T(e){return p.write((async()=>{if(!g.CrUXManager.instance().isEnabled())return r.nothing;const t=g.CrUXManager.instance(),i=await t.getFieldDataForPage(e);return Object.entries(i).some((([e,t])=>"warnings"!==e&&Boolean(t)))?r.nothing:Q`
<devtools-icon
class="origin-warning-icon"
name="warning-filled"
title=${ie(ee.pageHasNoData)}
></devtools-icon>
`}))}startCreation(){const e=l.TargetManager.TargetManager.instance().inspectedURL(),t=this.#k(e)||"";this.#f.addNewItem(-1,{developmentOrigin:t,productionOrigin:""})}renderItem(e){const t=document.createElement("div");let i,n;return t.classList.add("origin-mapping-row"),t.role="row",e.isTitleRow?(t.classList.add("header"),i="columnheader",n=r.nothing):(i="cell",n=r.Directives.until(this.#T(e.productionOrigin))),r.render(Q`
<div class="origin-mapping-cell development-origin" role=${i}>
<div class="origin" title=${e.developmentOrigin}>${e.developmentOrigin}</div>
</div>
<div class="origin-mapping-cell production-origin" role=${i}>
${n}
<div class="origin" title=${e.productionOrigin}>${e.productionOrigin}</div>
</div>
`,t,{host:this}),t}removeItemRequested(e,t){const i=this.#S();i.splice(t-1,1),this.#x(i)}commitEdit(e,t,i){e.developmentOrigin=this.#k(t.control(ne).value)||"",e.productionOrigin=this.#k(t.control(se).value)||"";const n=this.#S();i&&n.push(e),this.#x(n)}beginEdit(e){const t=this.#C();return t.control(ne).value=e.developmentOrigin,t.control(se).value=e.productionOrigin,t}#$(e,t,i){const n=this.#k(i.value);if(!n)return{valid:!1,errorMessage:ie(ee.invalidOrigin,{PH1:i.value})};const s=this.#S();for(let e=0;e<s.length;++e){if(e===t-1)continue;if(s[e].developmentOrigin===n)return{valid:!0,errorMessage:ie(ee.alreadyMapped,{PH1:n})}}return{valid:!0}}#P(e,t,i){return this.#k(i.value)?{valid:!0}:{valid:!1,errorMessage:ie(ee.invalidOrigin,{PH1:i.value})}}#C(){if(this.#y)return this.#y;const e=new s.ListWidget.Editor;this.#y=e;const t=e.contentElement().createChild("div","origin-mapping-editor"),i=e.createInput(ne,"text",ie(ee.developmentOrigin),this.#$.bind(this)),n=e.createInput(se,"text",ie(ee.productionOrigin),this.#P.bind(this));return r.render(Q`
<label class="development-origin-input">
${ie(ee.developmentOrigin)}
${i}
</label>
<label class="production-origin-input">
${ie(ee.productionOrigin)}
${n}
</label>
`,t,{host:this}),e}}customElements.define("devtools-origin-map",re);var oe=Object.freeze({__proto__:null,OriginMap:re}),ae={cssText:`:host{display:block}:host *{box-sizing:border-box}devtools-dialog{--override-transparent:color-mix(in srgb,var(--color-background) 80%,transparent)}.section-title{font-size:var(--sys-typescale-headline5-size);line-height:var(--sys-typescale-headline5-line-height);font-weight:var(--ref-typeface-weight-medium);margin:0}.privacy-disclosure{margin:8px 0}.url-override{margin:8px 0;display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;max-width:max-content}details > summary{font-size:var(--sys-typescale-body4-size);line-height:var(--sys-typescale-body4-line-height);font-weight:var(--ref-typeface-weight-medium)}.content{max-width:360px;box-sizing:border-box}.open-button-section{display:flex;flex-direction:row}.origin-mapping-grid{border:1px solid var(--sys-color-divider);margin-top:8px}.origin-mapping-description{margin-bottom:8px}.origin-mapping-button-section{display:flex;flex-direction:column;align-items:center;margin-top:var(--sys-size-6)}.config-button{margin-left:auto}.advanced-section-contents{margin:4px 0 14px}.buttons-section{display:flex;justify-content:space-between;margin-top:var(--sys-size-6);margin-bottom:var(--sys-size-2);devtools-button.enable{float:right}}input[type="checkbox"]{height:12px;width:12px;min-height:12px;min-width:12px;margin:6px}input[type="text"][disabled]{color:var(--sys-color-state-disabled)}.warning{margin:2px 8px;color:var(--color-error-text)}x-link{color:var(--sys-color-primary);text-decoration-line:underline}.divider{margin:10px 0;border:none;border-top:1px solid var(--sys-color-divider)}\n/*# sourceURL=${import.meta.resolve("./fieldSettingsDialog.css")} */\n`};const le=new CSSStyleSheet;le.replaceSync(ae.cssText);const de={setUp:"Set up",configure:"Configure",ok:"Ok",optOut:"Opt out",cancel:"Cancel",onlyFetchFieldData:"Always show field data for the below URL",url:"URL",doesNotHaveSufficientData:"The Chrome UX Report does not have sufficient real-world speed data for this page.",configureFieldData:"Configure field data fetching",fetchAggregated:"Fetch aggregated field data from the {PH1} to help you contextualize local measurements with what real users experience on the site.",privacyDisclosure:"Privacy disclosure",whenPerformanceIsShown:"When DevTools is open, the URLs you visit will be sent to Google to query field data. These requests are not tied to your Google account.",advanced:"Advanced",mapDevelopmentOrigins:"Set a development origin to automatically get relevant field data for its production origin.",new:"New",invalidOrigin:'"{PH1}" is not a valid origin or URL.'},ce=t.i18n.registerUIStrings("panels/timeline/components/FieldSettingsDialog.ts",de),he=t.i18n.getLocalizedString.bind(void 0,ce),{html:ge,nothing:pe,Directives:{ifDefined:ue}}=r;class me extends Event{static eventName="showdialog";constructor(){super(me.eventName)}}class ve extends HTMLElement{#e=this.attachShadow({mode:"open"});#L;#R=g.CrUXManager.instance().getConfigSetting();#I="";#M=!1;#E="";#D;constructor(){super();const e=g.CrUXManager.instance();this.#R=e.getConfigSetting(),this.#H(),this.#i()}#H(){const e=this.#R.get();this.#I=e.override||"",this.#M=e.overrideEnabled||!1,this.#E=""}#F(e){const t=this.#R.get();this.#R.set({...t,enabled:e,override:this.#I,overrideEnabled:this.#M})}#N(){n.ScheduledRender.scheduleRender(this,this.#i)}async#z(e){const t=g.CrUXManager.instance(),i=await t.getFieldDataForPage(e);return Object.entries(i).some((([e,t])=>"warnings"!==e&&Boolean(t)))}async#O(e){if(e&&this.#M){if(!this.#k(this.#I))return this.#E=he(de.invalidOrigin,{PH1:this.#I}),void n.ScheduledRender.scheduleRender(this,this.#i);if(!await this.#z(this.#I))return this.#E=he(de.doesNotHaveSufficientData),void n.ScheduledRender.scheduleRender(this,this.#i)}this.#F(e),this.#A()}#_(){if(!this.#L)throw new Error("Dialog not found");this.#H(),this.#L.setDialogVisible(!0),n.ScheduledRender.scheduleRender(this,this.#i),this.dispatchEvent(new me)}#A(e){if(!this.#L)throw new Error("Dialog not found");this.#L.setDialogVisible(!1),e&&e.stopImmediatePropagation(),n.ScheduledRender.scheduleRender(this,this.#i)}connectedCallback(){this.#e.adoptedStyleSheets=[le,u.textInputStyles,u.checkboxStyles],this.#R.addChangeListener(this.#N,this),n.ScheduledRender.scheduleRender(this,this.#i)}disconnectedCallback(){this.#R.removeChangeListener(this.#N,this)}#U(){return this.#R.get().enabled?ge`
<devtools-button
class="config-button"
@click=${this.#_}
.data=${{variant:"outlined",title:he(de.configure)}}
jslog=${o.action("timeline.field-data.configure").track({click:!0})}
>${he(de.configure)}</devtools-button>
`:ge`
<devtools-button
class="setup-button"
@click=${this.#_}
.data=${{variant:"primary",title:he(de.setUp)}}
jslog=${o.action("timeline.field-data.setup").track({click:!0})}
data-field-data-setup
>${he(de.setUp)}</devtools-button>
`}#B(){return ge`
<devtools-button
@click=${()=>{this.#O(!0)}}
.data=${{variant:"primary",title:he(de.ok)}}
class="enable"
jslog=${o.action("timeline.field-data.enable").track({click:!0})}
data-field-data-enable
>${he(de.ok)}</devtools-button>
`}#V(){const e=this.#R.get().enabled?he(de.optOut):he(de.cancel);return ge`
<devtools-button
@click=${()=>{this.#O(!1)}}
.data=${{variant:"outlined",title:e}}
jslog=${o.action("timeline.field-data.disable").track({click:!0})}
data-field-data-disable
>${e}</devtools-button>
`}#q(e){e.stopPropagation();const t=e.target;this.#I=t.value,this.#E="",n.ScheduledRender.scheduleRender(this,this.#i)}#j(e){e.stopPropagation();const t=e.target;this.#M=t.checked,this.#E="",n.ScheduledRender.scheduleRender(this,this.#i)}#k(e){try{return new URL(e).origin}catch{return null}}#W(){return ge`
<div class="origin-mapping-description">${he(de.mapDevelopmentOrigins)}</div>
<devtools-origin-map
on-render=${n.Directives.nodeRenderedCallback((e=>{this.#D=e}))}
></devtools-origin-map>
<div class="origin-mapping-button-section">
<devtools-button
@click=${()=>this.#D?.startCreation()}
.data=${{variant:"text",title:he(de.new),iconName:"plus"}}
jslogContext=${"new-origin-mapping"}
>${he(de.new)}</devtools-button>
</div>
`}#i=()=>{const e=s.XLink.XLink.create("https://developer.chrome.com/docs/crux",t.i18n.lockedString("Chrome UX Report")),i=t.i18n.getFormatLocalizedString(ce,de.fetchAggregated,{PH1:e}),a=ge`
<div class="open-button-section">${this.#U()}</div>
<devtools-dialog
@clickoutsidedialog=${this.#A}
.position=${"auto"}
.horizontalAlignment=${"center"}
.jslogContext=${"timeline.field-data.settings"}
.dialogTitle=${he(de.configureFieldData)}
on-render=${n.Directives.nodeRenderedCallback((e=>{this.#L=e}))}
>
<div class="content">
<div>${i}</div>
<div class="privacy-disclosure">
<h3 class="section-title">${he(de.privacyDisclosure)}</h3>
<div>${he(de.whenPerformanceIsShown)}</div>
</div>
<details aria-label=${he(de.advanced)}>
<summary>${he(de.advanced)}</summary>
<div class="advanced-section-contents">
${this.#W()}
<hr class="divider">
<label class="url-override">
<input
type="checkbox"
.checked=${this.#M}
@change=${this.#j}
aria-label=${he(de.onlyFetchFieldData)}
jslog=${o.toggle().track({click:!0}).context("field-url-override-enabled")}
/>
${he(de.onlyFetchFieldData)}
</label>
<input
type="text"
@keyup=${this.#q}
@change=${this.#q}
class="devtools-text-input"
.disabled=${!this.#M}
.value=${this.#I}
placeholder=${ue(this.#M?he(de.url):void 0)}
/>
${this.#E?ge`<div class="warning" role="alert" aria-label=${this.#E}>${this.#E}</div>`:pe}
</div>
</details>
<div class="buttons-section">
${this.#V()}
${this.#B()}
</div>
</div>
</devtools-dialog>
`;r.render(a,this.#e,{host:this})}}customElements.define("devtools-field-settings-dialog",ve);var be=Object.freeze({__proto__:null,FieldSettingsDialog:ve,ShowDialog:me}),fe={cssText:`.ignore-list-setting-content{max-width:var(--sys-size-30)}.ignore-list-setting-description{margin-bottom:5px}.regex-row{display:flex;dt-checkbox{flex:auto}devtools-button{height:24px}&:not(:hover) devtools-button{display:none}}.new-regex-row{display:flex;.new-regex-text-input{flex:auto}.harmony-input[type="text"]{border:1px solid var(--sys-color-neutral-outline);border-radius:4px;outline:none;&.error-input,\n &:invalid{border-color:var(--sys-color-error)}&:not(.error-input, :invalid):focus{border-color:var(--sys-color-state-focus-ring)}&:not(.error-input, :invalid):hover:not(:focus){background:var(--sys-color-state-hover-on-subtle)}}}\n/*# sourceURL=${import.meta.resolve("./ignoreListSetting.css")} */\n`};const ye=new CSSStyleSheet;ye.replaceSync(fe.cssText);const{html:we}=r,Se={showIgnoreListSettingDialog:"Show ignore list setting dialog",ignoreList:"Ignore list",ignoreListDescription:"Add regular expression rules to remove matching scripts from the flame chart.",ignoreScriptsWhoseNamesMatchS:"Ignore scripts whose names match ''{regex}''",removeRegex:"Remove the regex: ''{regex}''",addNewRegex:"Add a regular expression rule for the script's URL",ignoreScriptsWhoseNamesMatchNewRegex:"Ignore scripts whose names match the new regex"},xe=t.i18n.registerUIStrings("panels/timeline/components/IgnoreListSetting.ts",Se),ke=t.i18n.getLocalizedString.bind(void 0,xe);class Te extends HTMLElement{#e=this.attachShadow({mode:"open"});#K=this.#i.bind(this);#G=a.Settings.Settings.instance().moduleSetting("enable-ignore-listing");#Y=this.#X().getAsArray();#J=s.UIUtils.CheckboxLabel.create(void 0,!1,void 0,"timeline.ignore-list-new-regex.checkbox");#Z=s.UIUtils.createInput("new-regex-text-input","text","timeline.ignore-list-new-regex.text");#Q=null;constructor(){super(),this.#ee(),a.Settings.Settings.instance().moduleSetting("skip-stack-frames-pattern").addChangeListener(this.#te.bind(this)),a.Settings.Settings.instance().moduleSetting("enable-ignore-listing").addChangeListener(this.#te.bind(this))}connectedCallback(){this.#e.adoptedStyleSheets=[ye],this.#te(),this.addEventListener("contextmenu",(e=>{e.stopPropagation()}))}#te(){n.ScheduledRender.scheduleRender(this,this.#K)}#X(){return a.Settings.Settings.instance().moduleSetting("skip-stack-frames-pattern")}#ie(){this.#Q={pattern:this.#Z.value,disabled:!1,disabledForUrl:void 0},this.#Y.push(this.#Q)}#ne(){if(!this.#Q)return;const e=this.#Y.pop();e&&e!==this.#Q&&(console.warn("The last regex is not the editing one."),this.#Y.push(e)),this.#Q=null,this.#X().setAsArray(this.#Y)}#se(){this.#J.checkboxElement.checked=!1,this.#Z.value=""}#re(){const e=this.#Z.value.trim();this.#ne(),Ce(e)&&(m.IgnoreListManager.IgnoreListManager.instance().addRegexToIgnoreList(e),this.#se())}#oe(e){if(e.key===h.KeyboardUtilities.ENTER_KEY)return this.#re(),void this.#ie();e.key===h.KeyboardUtilities.ESCAPE_KEY&&(e.stopImmediatePropagation(),this.#ne(),this.#se(),this.#Z.blur())}#ae(){if(this.#Q){const e=this.#Y[this.#Y.length-1];if(e&&e===this.#Q)return this.#Y.slice(0,-1)}return this.#Y}#le(){const e=this.#Z.value.trim();this.#Q&&Ce(e)&&(this.#Q.pattern=e,this.#Q.disabled=!Boolean(e),this.#X().setAsArray(this.#Y))}#ee(){this.#Z.placeholder="/framework\\.js$";const e=ke(Se.ignoreScriptsWhoseNamesMatchNewRegex),t=ke(Se.addNewRegex);s.Tooltip.Tooltip.install(this.#J,e),s.Tooltip.Tooltip.install(this.#Z,t),this.#Z.addEventListener("blur",this.#re.bind(this),!1),this.#Z.addEventListener("keydown",this.#oe.bind(this),!1),this.#Z.addEventListener("input",this.#le.bind(this),!1),this.#Z.addEventListener("focus",this.#ie.bind(this),!1)}#de(){return we`
<div class='new-regex-row'>${this.#J}${this.#Z}</div>
`}#ce(e,t){e.disabled=!t.checkboxElement.checked,this.#X().setAsArray(this.#Y)}#he(e){this.#Y.splice(e,1),this.#X().setAsArray(this.#Y)}#ge(e,t){const i=s.UIUtils.CheckboxLabel.createWithStringLiteral(e.pattern,!e.disabled,void 0,"timeline.ignore-list-pattern"),n=ke(Se.ignoreScriptsWhoseNamesMatchS,{regex:e.pattern});return s.Tooltip.Tooltip.install(i,n),i.checkboxElement.ariaLabel=n,i.checkboxElement.addEventListener("change",this.#ce.bind(this,e,i),!1),we`
<div class='regex-row'>
${i}
<devtools-button
@click=${this.#he.bind(this,t)}
.data=${{variant:"icon",iconName:"bin",title:ke(Se.removeRegex,{regex:e.pattern}),jslogContext:"timeline.ignore-list-pattern.remove"}}></devtools-button>
</div>
`}#i(){if(!n.ScheduledRender.isScheduledRender(this))throw new Error("Ignore List setting dialog render was not scheduled");const e=we`
<devtools-button-dialog .data=${{openOnRender:!1,jslogContext:"timeline.ignore-list",variant:"toolbar",iconName:"compress",disabled:!this.#G.get(),iconTitle:ke(Se.showIgnoreListSettingDialog),horizontalAlignment:"auto",closeButton:!0,dialogTitle:ke(Se.ignoreList)}}>
<div class='ignore-list-setting-content'>
<div class='ignore-list-setting-description'>${ke(Se.ignoreListDescription)}</div>
${this.#ae().map(this.#ge.bind(this))}
${this.#de()}
</div>
</devtools-button-dialog>
`;r.render(e,this.#e,{host:this})}}function Ce(e){const t=e.trim();if(!t.length)return!1;let i;try{i=new RegExp(t)}catch{}return Boolean(i)}customElements.define("devtools-perf-ignore-list-setting",Te);var $e=Object.freeze({__proto__:null,IgnoreListSetting:Te,regexInputIsValid:Ce}),Pe={cssText:`:host{display:block}.breakdown{margin:0;padding:0;list-style:none;color:var(--sys-color-token-subtle)}.value{display:inline-block;padding:0 5px;color:var(--sys-color-on-surface)}\n/*# sourceURL=${import.meta.resolve("./interactionBreakdown.css")} */\n`};const Le=new CSSStyleSheet;Le.replaceSync(Pe.cssText);const{html:Re}=r,Ie={inputDelay:"Input delay",processingDuration:"Processing duration",presentationDelay:"Presentation delay"},Me=t.i18n.registerUIStrings("panels/timeline/components/InteractionBreakdown.ts",Ie),Ee=t.i18n.getLocalizedString.bind(void 0,Me);class De extends HTMLElement{#e=this.attachShadow({mode:"open"});#t=this.#i.bind(this);#pe=null;connectedCallback(){this.#e.adoptedStyleSheets=[Le]}set entry(e){e!==this.#pe&&(this.#pe=e,n.ScheduledRender.scheduleRender(this,this.#t))}#i(){if(!this.#pe)return;const e=t.TimeUtilities.formatMicroSecondsAsMillisFixed(this.#pe.inputDelay),i=t.TimeUtilities.formatMicroSecondsAsMillisFixed(this.#pe.mainThreadHandling),n=t.TimeUtilities.formatMicroSecondsAsMillisFixed(this.#pe.presentationDelay);r.render(Re`<ul class="breakdown">
<li data-entry="input-delay">${Ee(Ie.inputDelay)}<span class="value">${e}</span></li>
<li data-entry="processing-duration">${Ee(Ie.processingDuration)}<span class="value">${i}</span></li>
<li data-entry="presentation-delay">${Ee(Ie.presentationDelay)}<span class="value">${n}</span></li>
</ul>
`,this.#e,{host:this})}}customElements.define("devtools-interaction-breakdown",De);var He=Object.freeze({__proto__:null,InteractionBreakdown:De}),Fe={cssText:`.layout-shift-details-title,\n.cluster-details-title{padding-bottom:var(--sys-size-5);display:flex;align-items:center;.layout-shift-event-title,\n .cluster-event-title{background-color:var(--app-color-rendering);width:var(--sys-size-6);height:var(--sys-size-6);border:var(--sys-size-1) solid var(--sys-color-divider);display:inline-block;margin-right:var(--sys-size-3)}}.layout-shift-details-table{font:var(--sys-typescale-body4-regular);margin-bottom:var(--sys-size-4);text-align:left;border-block:var(--sys-size-1) solid var(--sys-color-divider);border-collapse:collapse;font-variant-numeric:tabular-nums;th,\n td{padding-right:var(--sys-size-4);min-width:var(--sys-size-20);max-width:var(--sys-size-28)}}.table-title{th{font:var(--sys-typescale-body4-medium)}tr{border-bottom:var(--sys-size-1) solid var(--sys-color-divider)}}.timeline-link{cursor:pointer;text-decoration:underline;color:var(--sys-color-primary);background:none;border:none;padding:0;font:inherit;text-align:left}.timeline-link.invalid-link{color:var(--sys-color-state-disabled)}.details-row{display:flex;min-height:var(--sys-size-9)}.title{color:var(--sys-color-token-subtle);overflow:hidden;padding-right:var(--sys-size-5);display:inline-block;vertical-align:top}.culprit{display:inline-flex;flex-direction:row;gap:var(--sys-size-3)}.value{display:inline-block;user-select:text;text-overflow:ellipsis;overflow:hidden;padding:0 var(--sys-size-3)}.layout-shift-summary-details,\n.layout-shift-cluster-summary-details{font:var(--sys-typescale-body4-regular);display:flex;flex-direction:column;column-gap:var(--sys-size-4);padding:var(--sys-size-6) var(--sys-size-6) 0 var(--sys-size-6)}.culprits{display:flex;flex-direction:column}.shift-row:not(:last-child){border-bottom:var(--sys-size-1) solid var(--sys-color-divider)}.total-row{font:var(--sys-typescale-body4-medium)}\n/*# sourceURL=${import.meta.resolve("./layoutShiftDetails.css")} */\n`};const Ne=new CSSStyleSheet;Ne.replaceSync(Fe.cssText);const ze=new CSSStyleSheet;ze.replaceSync(d.textButtonStyles.cssText);const{html:Oe}=r,Ae={startTime:"Start time",shiftScore:"Shift score",elementsShifted:"Elements shifted",culprit:"Culprit",injectedIframe:"Injected iframe",fontRequest:"Font request",nonCompositedAnimation:"Non-composited animation",animation:"Animation",parentCluster:"Parent cluster",cluster:"Layout shift cluster @ {PH1}",layoutShift:"Layout shift @ {PH1}",total:"Total",unsizedImage:"Unsized image"},_e=t.i18n.registerUIStrings("panels/timeline/components/LayoutShiftDetails.ts",Ae),Ue=t.i18n.getLocalizedString.bind(void 0,_e);class Be extends HTMLElement{#e=this.attachShadow({mode:"open"});#ue=null;#me=null;#ve=null;#be=!1;connectedCallback(){this.#e.adoptedStyleSheets=[Ne,ze],this.#i()}setData(e,t,i,n){this.#ue!==e&&(this.#ue=e,this.#me=t,this.#ve=i,this.#be=n,this.#i())}#fe(e){const t=f.EntryName.nameForEntry(e);return Oe`
<div class="layout-shift-details-title">
<div class="layout-shift-event-title"></div>
${t}
</div>
`}#ye(e,t){return Oe`
${t?.map((t=>void 0!==t.node_id?Oe`
<devtools-performance-node-link
.data=${{backendNodeId:t.node_id,frame:e.args.frame}}>
</devtools-performance-node-link>`:r.nothing))}`}#we(e){const t=e;if(!t)return null;const i=l.FrameManager.FrameManager.instance().getFrame(t);if(!i)return null;const n=b.Linkifier.Linkifier.linkifyRevealable(i,i.displayName());return Oe`
<span class="culprit"><span class="culprit-type">${Ue(Ae.injectedIframe)}: </span><span class="culprit-value">${n}</span></span>`}#Se(e){const t={tabStop:!0,showColumnNumber:!1,inlineFrameIndex:0,maxLength:20},i=b.Linkifier.Linkifier.linkifyURL(e.args.data.url,t);return Oe`
<span class="culprit"><span class="culprit-type">${Ue(Ae.fontRequest)}: </span><span class="culprit-value">${i}</span></span>`}#xe(e){this.dispatchEvent(new y.EventRef.EventReferenceClick(e))}#ke(e){const t=e.animation;return t?Oe`
<span class="culprit">
<span class="culprit-type">${Ue(Ae.nonCompositedAnimation)}: </span>
<button type="button" class="culprit-value timeline-link" @click=${()=>this.#xe(t)}>${Ue(Ae.animation)}</button>
</span>`:null}#Te(e,t){const i=Oe`
<devtools-performance-node-link
.data=${{backendNodeId:t,frame:e}}>
</devtools-performance-node-link>`;return Oe`
<span class="culprit"><span class="culprit-type">${Ue(Ae.unsizedImage)}: </span><span class="culprit-value">${i}</span></span>`}#Ce(e,t){return Oe`
${t?.fontRequests.map((e=>this.#Se(e)))}
${t?.iframeIds.map((e=>this.#we(e)))}
${t?.nonCompositedAnimations.map((e=>this.#ke(e)))}
${t?.unsizedImages.map((t=>this.#Te(e,t)))}
`}#$e(e,n){const s=i.Types.Timing.Micro(e.ts-n.Meta.traceBounds.min);if(e===this.#ue)return Oe`${t.TimeUtilities.preciseMillisToString(v.Timing.microToMilli(s))}`;const r=t.TimeUtilities.formatMicroSecondsTime(s);return Oe`
<button type="button" class="timeline-link" @click=${()=>this.#xe(e)}>${Ue(Ae.layoutShift,{PH1:r})}</button>`}#Pe(e,t,i,n){const s=e.args.data?.weighted_score_delta;if(!s)return null;const o=Boolean(n&&(n.fontRequests.length||n.iframeIds.length||n.nonCompositedAnimations.length||n.unsizedImages.length));return Oe`
<tr class="shift-row" data-ts=${e.ts}>
<td>${this.#$e(e,t)}</td>
<td>${s.toFixed(4)}</td>
${this.#be?Oe`
<td>
<div class="elements-shifted">
${this.#ye(e,i)}
</div>
</td>`:r.nothing}
${o&&this.#be?Oe`
<td class="culprits">
${this.#Ce(e.args.frame,n)}
</td>`:r.nothing}
</tr>`}#Le(e,n){if(!e)return null;const s=i.Types.Timing.Micro(e.ts-(n?.Meta.traceBounds.min??0)),r=t.TimeUtilities.formatMicroSecondsTime(s);return Oe`
<span class="parent-cluster">${Ue(Ae.parentCluster)}:
<button type="button" class="timeline-link" @click=${()=>this.#xe(e)}>${Ue(Ae.cluster,{PH1:r})}</button>
</span>`}#Re(e){return Oe`
<td class="total-row">${Ue(Ae.total)}</td>
<td class="total-row">${e.clusterCumulativeScore.toFixed(4)}</td>`}#Ie(e,t,n){if(!t)return null;const s=e.args.data?.navigationId??i.Types.Events.NO_NAVIGATION,o=t.get(s)?.model.CLSCulprits;if(!o||o instanceof Error)return null;const a=o.shifts.get(e),l=e.args.data?.impacted_nodes??[],d=a&&(a.fontRequests.length||a.iframeIds.length||a.nonCompositedAnimations.length||a.unsizedImages.length),c=l?.length,h=o.clusters.find((t=>t.events.find((t=>t===e))));return Oe`
<table class="layout-shift-details-table">
<thead class="table-title">
<tr>
<th>${Ue(Ae.startTime)}</th>
<th>${Ue(Ae.shiftScore)}</th>
${c&&this.#be?Oe`
<th>${Ue(Ae.elementsShifted)}</th>`:r.nothing}
${d&&this.#be?Oe`
<th>${Ue(Ae.culprit)}</th> `:r.nothing}
</tr>
</thead>
<tbody>
${this.#Pe(e,n,l,a)}
</tbody>
</table>
${this.#Le(h,n)}
`}#Me(e,t,n){if(!t)return null;const s=e.navigationId??i.Types.Events.NO_NAVIGATION,o=t.get(s)?.model.CLSCulprits;if(!o||o instanceof Error)return null;const a=Array.from(o.shifts.entries()).filter((([t])=>e.events.includes(t))).map((([,e])=>e)).flatMap((e=>Object.values(e))).flat(),l=Boolean(a.length);return Oe`
<table class="layout-shift-details-table">
<thead class="table-title">
<tr>
<th>${Ue(Ae.startTime)}</th>
<th>${Ue(Ae.shiftScore)}</th>
${this.#be?Oe`
<th>${Ue(Ae.elementsShifted)}</th>`:r.nothing}
${l&&this.#be?Oe`
<th>${Ue(Ae.culprit)}</th> `:r.nothing}
</tr>
</thead>
<tbody>
${e.events.map((e=>{const t=o.shifts.get(e),i=e.args.data?.impacted_nodes??[];return this.#Pe(e,n,i,t)}))}
${this.#Re(e)}
</tbody>
</table>
`}#i(){if(!this.#ue||!this.#ve)return;const e=Oe`
<div class="layout-shift-summary-details">
<div
class="event-details"
@mouseover=${this.#Ee}
@mouseleave=${this.#Ee}
>
${this.#fe(this.#ue)}
${i.Types.Events.isSyntheticLayoutShift(this.#ue)?this.#Ie(this.#ue,this.#me,this.#ve):this.#Me(this.#ue,this.#me,this.#ve)}
</div>
</div>
`;r.render(e,this.#e,{host:this})}#Ee(e){const t="mouseover"===e.type;if("mouseleave"===e.type&&this.dispatchEvent(new CustomEvent("toggle-popover",{detail:{show:t},bubbles:!0,composed:!0})),!(e.target instanceof HTMLElement&&this.#ue))return;const n=e.target.closest("tbody tr");if(!n?.parentElement)return;const s=i.Types.Events.isSyntheticLayoutShift(this.#ue)?this.#ue:this.#ue.events.find((e=>e.ts===parseInt(n.getAttribute("data-ts")??"",10)));this.dispatchEvent(new CustomEvent("toggle-popover",{detail:{event:s,show:t},bubbles:!0,composed:!0}))}}customElements.define("devtools-performance-layout-shift-details",Be);var Ve=Object.freeze({__proto__:null,LayoutShiftDetails:Be}),qe={cssText:`:host{display:flex;align-items:center;max-width:100%;height:20px}devtools-select-menu{min-width:160px;max-width:100%;height:20px}\n/*# sourceURL=${import.meta.resolve("./networkThrottlingSelector.css")} */\n`};const je=new CSSStyleSheet;je.replaceSync(qe.cssText);const{html:We,nothing:Ke}=r,Ge={network:"Network: {PH1}",networkThrottling:"Network throttling: {PH1}",recommendedThrottling:"{PH1} – recommended",recommendedThrottlingReason:"Consider changing setting to simulate real user environments",disabled:"Disabled",presets:"Presets",custom:"Custom",add:"Add…"},Ye=t.i18n.registerUIStrings("panels/timeline/components/NetworkThrottlingSelector.ts",Ge),Xe=t.i18n.getLocalizedString.bind(void 0,Ye);class Je extends HTMLElement{#e=this.attachShadow({mode:"open"});#De;#h=[];#He;#Fe=null;constructor(){super(),this.#De=a.Settings.Settings.instance().moduleSetting("custom-network-conditions"),this.#Ne(),this.#He=l.NetworkManager.MultitargetNetworkManager.instance().networkConditions(),this.#i()}set recommendedConditions(e){this.#Fe=e,n.ScheduledRender.scheduleRender(this,this.#i)}connectedCallback(){this.#e.adoptedStyleSheets=[je],l.NetworkManager.MultitargetNetworkManager.instance().addEventListener("ConditionsChanged",this.#ze,this),this.#ze(),this.#De.addChangeListener(this.#Oe,this)}disconnectedCallback(){l.NetworkManager.MultitargetNetworkManager.instance().removeEventListener("ConditionsChanged",this.#ze,this),this.#De.removeChangeListener(this.#Oe,this)}#Ne(){this.#h=[{name:Xe(Ge.disabled),items:[l.NetworkManager.NoThrottlingConditions]},{name:Xe(Ge.presets),items:c.ThrottlingPresets.ThrottlingPresets.networkPresets},{name:Xe(Ge.custom),items:this.#De.get(),showCustomAddOption:!0,jslogContext:"custom-network-throttling-item"}]}#ze(){this.#He=l.NetworkManager.MultitargetNetworkManager.instance().networkConditions(),n.ScheduledRender.scheduleRender(this,this.#i)}#v(e){const t=this.#h.flatMap((e=>e.items)).find((t=>this.#Ae(t)===e.itemValue));t&&l.NetworkManager.MultitargetNetworkManager.instance().setNetworkConditions(t)}#Oe(){this.#Ne(),n.ScheduledRender.scheduleRender(this,this.#i)}#_e(e){return e.title instanceof Function?e.title():e.title}#Ue(){a.Revealer.reveal(this.#De)}#Ae(e){return e.i18nTitleKey||this.#_e(e)}#i=()=>{const e=this.#_e(this.#He),t=this.#Ae(this.#He);let i;this.#Fe&&this.#He===l.NetworkManager.NoThrottlingConditions&&(i=We`<devtools-button
title=${Xe(Ge.recommendedThrottlingReason)}
.iconName=${"info"}
.variant=${"icon"}
></devtools-button>`);const n=We`
<devtools-select-menu
@selectmenuselected=${this.#v}
.showDivider=${!0}
.showArrow=${!0}
.sideButton=${!1}
.showSelectedItem=${!0}
.jslogContext=${"network-conditions"}
.buttonTitle=${Xe(Ge.network,{PH1:e})}
.title=${Xe(Ge.networkThrottling,{PH1:e})}
>
${this.#h.map((e=>We`
<devtools-menu-group .name=${e.name} .title=${e.name}>
${e.items.map((i=>{let n=this.#_e(i);i===this.#Fe&&(n=Xe(Ge.recommendedThrottling,{PH1:n}));const s=this.#Ae(i),r=e.jslogContext||h.StringUtilities.toKebabCase(i.i18nTitleKey||n);return We`
<devtools-menu-item
.value=${s}
.selected=${t===s}
.title=${n}
jslog=${o.item(r).track({click:!0})}
>
${n}
</devtools-menu-item>
`}))}
${e.showCustomAddOption?We`
<devtools-menu-item
.value=${1}
.title=${Xe(Ge.add)}
jslog=${o.action("add").track({click:!0})}
@click=${this.#Ue}
>
${Xe(Ge.add)}
</devtools-menu-item>
`:Ke}
</devtools-menu-group>
`))}
</devtools-select-menu>
${i}
`;r.render(n,this.#e,{host:this})}}customElements.define("devtools-network-throttling-selector",Je);var Ze=Object.freeze({__proto__:null,NetworkThrottlingSelector:Je}),Qe={cssText:`.metric-card{border-radius:var(--sys-shape-corner-small);padding:14px 16px;background-color:var(--sys-color-surface3);height:100%;box-sizing:border-box;&:not(:hover) .title-help{visibility:hidden}}.title{display:flex;justify-content:space-between;font-size:var(--sys-typescale-headline5-size);line-height:var(--sys-typescale-headline5-line-height);font-weight:var(--ref-typeface-weight-medium);margin:0;margin-bottom:6px}.title-help{height:var(--sys-typescale-headline5-line-height);margin-left:4px}.metric-values-section{position:relative;display:flex;column-gap:8px;margin-bottom:8px}.metric-values-section:focus-visible{outline:2px solid -webkit-focus-ring-color}.metric-source-block{flex:1}.metric-source-value{font-size:32px;line-height:36px;font-weight:var(--ref-typeface-weight-regular)}.metric-source-label{font-weight:var(--ref-typeface-weight-medium)}.warning{margin-top:4px;color:var(--sys-color-error);font-size:var(--sys-typescale-body4-size);line-height:var(--sys-typescale-body4-line-height);display:flex;&::before{content:" ";width:var(--sys-typescale-body4-line-height);height:var(--sys-typescale-body4-line-height);mask-size:var(--sys-typescale-body4-line-height);mask-image:var(--image-file-warning);background-color:var(--sys-color-error);margin-right:4px;flex-shrink:0}}.good-bg{background-color:var(--app-color-performance-good)}.needs-improvement-bg{background-color:var(--app-color-performance-ok)}.poor-bg{background-color:var(--app-color-performance-bad)}.divider{width:100%;border:0;border-bottom:1px solid var(--sys-color-divider);margin:8px 0;box-sizing:border-box}.compare-text{margin-top:8px}.environment-recs-intro{margin-top:8px}.environment-recs{margin:9px 0}.environment-recs > summary{font-weight:var(--ref-typeface-weight-medium);margin-bottom:4px;font-size:var(--sys-typescale-body4-size);line-height:var(--sys-typescale-body4-line-height);display:flex;&::before{content:" ";width:var(--sys-typescale-body4-line-height);height:var(--sys-typescale-body4-line-height);mask-size:var(--sys-typescale-body4-line-height);mask-image:var(--image-file-triangle-right);background-color:var(--icon-default);margin-right:4px;flex-shrink:0}}details.environment-recs[open] > summary::before{mask-image:var(--image-file-triangle-down)}.environment-recs-list{margin:0}.detailed-compare-text{margin-bottom:8px}.bucket-summaries{margin-top:8px;white-space:nowrap}.bucket-summaries.histogram{display:grid;grid-template-columns:minmax(min-content,auto) minmax(40px,60px) max-content;grid-auto-rows:1fr;column-gap:8px;place-items:center flex-end}.bucket-label{justify-self:start;font-weight:var(