@react-native/debugger-frontend
Version:
Debugger frontend for React Native based on Chrome DevTools
82 lines (81 loc) • 18.1 kB
JavaScript
import*as t from"../../../core/platform/platform.js";import*as e from"../../../services/window_bounds/window_bounds.js";import*as o from"../helpers/helpers.js";import*as i from"../render_coordinator/render_coordinator.js";import*as s from"../../lit-html/lit-html.js";import*as n from"../../visual_logging/visual_logging.js";import*as r from"../../../core/i18n/i18n.js";import*as a from"../icon_button/icon_button.js";import*as l from"../buttons/buttons.js";const d=new CSSStyleSheet;d.replaceSync(":host{--override-transparent:rgb(0 0 0/0%);display:var(--dialog-display)}dialog::backdrop{background:var(--override-transparent)}dialog{background:transparent;border:none;border-radius:4px;top:var(--dialog-top);padding:var(--dialog-padding);left:var(--dialog-left);right:var(--dialog-right);margin:var(--dialog-margin);margin-left:var(--dialog-margin-left,0);margin-bottom:var(--dialog-margin-bottom);animation-name:slideIn;animation-duration:100ms;animation-timing-function:cubic-bezier(0,0,0.3,1);overflow:hidden}dialog:focus,\ndialog:focus-visible{outline:none}#content{min-width:var(--content-min-width);background:var(--color-background-elevation-dark-only);border-radius:4px;padding-top:var(--content-padding-top);padding-bottom:var(--content-padding-bottom);box-shadow:var(--override-content-box-shadow);max-height:var(--dialog-max-height);max-width:var(--dialog-max-width);overflow:auto;outline:none;clip-path:polygon(var(--content-clip-path))}#content-wrap{filter:drop-shadow(0 1px 2px rgb(60 64 67/30%)) drop-shadow(0 2px 0 rgb(60 64 67/15%))}@keyframes slideIn{from{transform:translateY(var(--dialog-offset-y));opacity:0%}to{opacity:100%}}\n/*# sourceURL=dialog.css */\n");const h=i.RenderCoordinator.RenderCoordinator.instance(),c="HTMLDialogElement"in globalThis,g=10,p=30,u="MODAL";class m extends HTMLElement{static litTagName=s.literal`devtools-dialog`;#t=this.attachShadow({mode:"open"});#e=this.#o.bind(this);#i=this.#s.bind(this);#n=this.#r.bind(this);#a={origin:u,position:"bottom",horizontalAlignment:"center",showConnector:!1,getConnectorCustomXPosition:null,dialogShownCallback:null,windowBoundsService:e.WindowBoundsService.WindowBoundsServiceImpl.instance(),closeOnESC:!0,closeOnScroll:!0,jslogContext:""};#l=null;#d=!1;#h=!1;#c=new DOMRect(0,0,0,0);#g=new DOMRect(0,0,0,0);#p=null;#u=null;#m=new MutationObserver(this.#i);#w=new ResizeObserver(this.#b.bind(this));#v=this.windowBoundsService.getDevToolsBoundingElement();#y=this.#D.bind(this);get showConnector(){return this.#a.showConnector}set showConnector(t){this.#a.showConnector=t,this.#x()}get origin(){return this.#a.origin}set origin(t){this.#a.origin=t,this.#x()}get position(){return this.#a.position}set position(t){this.#a.position=t,this.#x()}get horizontalAlignment(){return this.#a.horizontalAlignment}set horizontalAlignment(t){this.#a.horizontalAlignment=t,this.#x()}get windowBoundsService(){return this.#a.windowBoundsService}set windowBoundsService(t){this.#a.windowBoundsService=t,this.#v=this.windowBoundsService.getDevToolsBoundingElement(),this.#x()}get bestVerticalPosition(){return this.#p}get bestHorizontalAlignment(){return this.#u}get getConnectorCustomXPosition(){return this.#a.getConnectorCustomXPosition}set getConnectorCustomXPosition(t){this.#a.getConnectorCustomXPosition=t,this.#x()}get dialogShownCallback(){return this.#a.dialogShownCallback}get jslogContext(){return this.#a.jslogContext}set dialogShownCallback(t){this.#a.dialogShownCallback=t,this.#x()}set closeOnESC(t){this.#a.closeOnESC=t,this.#x()}set closeOnScroll(t){this.#a.closeOnScroll=t,this.#x()}set jslogContext(t){this.#a.jslogContext=t,this.#x()}#b(){this.#g=this.#f().getBoundingClientRect()}#x(){o.ScheduledRender.scheduleRender(this,this.#e)}connectedCallback(){this.#t.adoptedStyleSheets=[d],window.addEventListener("resize",this.#i),this.#m.observe(this.#v,{childList:!0,subtree:!0}),this.#v.addEventListener("wheel",this.#n),this.style.setProperty("--dialog-padding","0"),this.style.setProperty("--override-content-box-shadow","none"),this.style.setProperty("--dialog-display",c?"block":"none"),this.style.setProperty("--override-dialog-content-border","10px solid transparent"),this.style.setProperty("--dialog-padding","3px 5px")}disconnectedCallback(){window.removeEventListener("resize",this.#i),this.#v.removeEventListener("wheel",this.#n),this.#m.disconnect(),this.#w.disconnect()}#f(){if(!this.#l){if(this.#l=this.#t.querySelector("dialog"),!this.#l)throw new Error("Dialog not found");this.#w.observe(this.#l)}return this.#l}getHitArea(){return this.#c}async setDialogVisible(t){t?await this.#C():this.#S()}async#P(t){if(t.stopPropagation(),t instanceof PointerEvent&&""===t.pointerType)return;const e=this.#E(t),o=this.#$(t);if(!e)if("pointermove"!==t.type)this.dispatchEvent(new b);else{if(o)return;this.dispatchEvent(new w)}}#E(t){const e=this.#g,o="bottom"===this.bestVerticalPosition?20:-20,i=t.pageX>=e.left&&t.pageX<=e.left+e.width,s=t.pageY>=e.top+o&&t.pageY<=e.top+e.height+o;return i&&s}#$(t){const e=this.#c,o=t.pageX>=e.left&&t.pageX<=e.left+e.width,i=t.pageY>=e.top&&t.pageY<=e.top+e.height;return o&&i}#k(t){if(!t||t===u)throw new Error("Dialog origin is null");const e=t instanceof Function?t():t;return e instanceof DOMPoint?{top:e.y,bottom:e.y,left:e.x,right:e.x}:e instanceof HTMLElement?e.getBoundingClientRect():e}#B(t,e){return e.right-t.left>t.right-e.left?"left":"right"}#A(t,e,o){return t.bottom+e>o.height&&t.top-e>o.top?"top":"bottom"}#R(){this.#a.origin&&(this.#d=!0,h.read((()=>{const e=this.#v.getBoundingClientRect(),o=e.width,i=e.height,s=e.left,n=e.top,r=e.right;if(this.#a.origin===u)return void h.write((()=>{this.style.setProperty("--dialog-top",`${n}px`),this.style.setProperty("--dialog-left",`${s}px`),this.style.setProperty("--dialog-margin","auto"),this.style.setProperty("--dialog-margin-left","auto"),this.style.setProperty("--dialog-margin-bottom","auto"),this.style.setProperty("--dialog-max-height",i-p+"px"),this.style.setProperty("--dialog-max-width",o-p+"px"),this.style.setProperty("--dialog-right",document.body.clientWidth-r+"px")}));const a=this.#a.origin,l=this.#k(a),{top:d,right:c,bottom:m,left:w}=l,b=(w+c)/2,v=c-w+g,y=document.body.clientWidth,D=this.#a.getConnectorCustomXPosition?this.#a.getConnectorCustomXPosition():b;h.write((()=>{this.style.setProperty("--dialog-top","0");const a=this.#f();a.style.visibility="hidden",this.#d&&!a.hasAttribute("open")&&(a.showModal(),this.setAttribute("open",""),this.#d=!1);const{width:h,height:u}=a.getBoundingClientRect();if(this.#u="auto"===this.#a.horizontalAlignment?this.#B(l,e):this.#a.horizontalAlignment,this.#p="auto"===this.#a.position?this.#A(l,u,e):this.#a.position,"auto"===this.#u||"auto"===this.#p)return;this.#c.height=m-d+g*(this.showConnector?2:1),this.#c.width=v;let x=0;this.style.setProperty("--content-min-width",D-w+20+10+"px"),this.style.setProperty("--dialog-left","auto"),this.style.setProperty("--dialog-right","auto"),this.style.setProperty("--dialog-margin","0");const f=this.showConnector?15:0;switch(this.#u){case"left":{const t=Math.max(w-f,s),e=r-t-p;x=D-t-5,this.style.setProperty("--dialog-left",`${t}px`),this.#c.x=w,this.style.setProperty("--dialog-max-width",`${e}px`);break}case"right":{const t=y-c,e=y-r,o=Math.max(t-f,e),i=y-o,n=i-s-p,a=Math.min(n,h);x=D-(i-a),this.#c.x=y-o-v,this.style.setProperty("--dialog-right",`${o}px`),this.style.setProperty("--dialog-max-width",`${n}px`);break}case"center":{const t=Math.min(o-p,h);let e=Math.max(b-.5*t,s);e=Math.min(e,r-t),x=D-e-5,this.style.setProperty("--dialog-left",`${e}px`),this.#c.x=b-.5*v,this.style.setProperty("--dialog-max-width",o-p+"px");break}default:t.assertNever(this.#u,`Unknown alignment type: ${this.#u}`)}const C=this.showConnector?g:0,S=x-10,P=x+10;let[E,$,k,B,A,R,I,O,T]=["","","","","","","","","",""];switch(this.#p){case"top":{const t="calc(100% - 10px)";this.#a.showConnector&&(E="0 0",$="100% 0",k=`100% calc(${t} - 2px)`,B=`calc(100% - 2px) ${t}`,A=`${S}px ${t}`,R=`${x}px 100%`,I=`${P}px ${t}`,O=`2px ${t}`,T=`0 calc(${t} - 2px)`),this.style.setProperty("--content-padding-bottom",`${g+(this.#a.showConnector?g:0)}px`),this.style.setProperty("--content-padding-top","10px"),this.style.setProperty("--dialog-top","0"),this.style.setProperty("--dialog-margin","auto"),this.style.setProperty("--dialog-margin-bottom",innerHeight-d+"px"),this.#c.y=d-20,this.style.setProperty("--dialog-offset-y","20px"),this.style.setProperty("--dialog-max-height",i-(innerHeight-d)-p-C+"px");break}case"bottom":this.#a.showConnector&&(E="0 12px",$="2px 10px",k=`${S}px 10px`,B=`${x}px 0`,A=`${P}px 10px`,R="calc(100% - 2px) 10px",I="100% 12px",O="100% 100%",T="0 100%"),this.style.setProperty("--content-padding-top",`${g+(this.#a.showConnector?g:0)}px`),this.style.setProperty("--content-padding-bottom","10px"),this.style.setProperty("--dialog-top",`${m}px`),this.#c.y=d,this.style.setProperty("--dialog-offset-y","-20px"),this.style.setProperty("--dialog-max-height",i-(m-n)-p-C+"px");break;default:t.assertNever(this.#p,`Unknown position type: ${this.#p}`)}const N=[E,$,k,B,A,R,I,O,T].join();this.style.setProperty("--content-clip-path",N),a.close(),a.style.visibility=""}))})))}async#C(){if(!c)return;if(this.#d||this.hasAttribute("open"))return;this.#d=!0,this.#R(),await h.done(),this.#d=!1;const t=this.#f();t.hasAttribute("open")||t.showModal(),this.#a.dialogShownCallback&&await this.#a.dialogShownCallback(),this.#b(),document.body.addEventListener("keydown",this.#y)}#r(t){!this.#E(t)&&this.#a.closeOnScroll&&this.#f().hasAttribute("open")&&(this.#S(),this.dispatchEvent(new v))}#D(e){this.#f().hasAttribute("open")&&this.#a.closeOnESC&&e.key===t.KeyboardUtilities.ESCAPE_KEY&&(e.stopPropagation(),e.preventDefault(),this.#S(),this.dispatchEvent(new v))}#I(t){t.stopPropagation(),t.preventDefault(),this.#f().hasAttribute("open")&&this.#a.closeOnESC&&this.dispatchEvent(new v)}#s(){this.#l?.hasAttribute("open")&&this.#v!==document.body&&(this.#S(),this.dispatchEvent(new v))}#S(){!this.#h&&this.#f().hasAttribute("open")&&(this.#h=!0,h.write((()=>{this.#c.width=0,this.removeAttribute("open"),this.#f().close(),this.#h=!1,document.body.removeEventListener("keydown",this.#y)})))}getDialogBounds(){return this.#g}#o(){if(!o.ScheduledRender.isScheduledRender(this))throw new Error("Dialog render was not scheduled");c?(s.render(s.html`
<dialog =${this.#P} =${this.#P} =${this.#I}
jslog=${n.dialog(this.#a.jslogContext).track({resize:!0,keydown:"Escape"}).parent("mapped")}>
<div id="content-wrap">
<div id="content">
<slot></slot>
</div>
</div>
</dialog>
`,this.#t,{host:this}),n.setMappedParent(this.#f(),this.parentElementOrShadowHost())):s.render(s.html`
<slot></slot>
`,this.#t,{host:this})}}customElements.define("devtools-dialog",m);class w extends Event{static eventName="pointerleftdialog";constructor(){super(w.eventName,{bubbles:!0,composed:!0})}}class b extends Event{static eventName="clickoutsidedialog";constructor(){super(b.eventName,{bubbles:!0,composed:!0})}}class v extends Event{static eventName="forceddialogclose";constructor(){super(v.eventName,{bubbles:!0,composed:!0})}}var y=Object.freeze({__proto__:null,CONNECTOR_HEIGHT:g,DIALOG_SIDE_PADDING:5,DIALOG_VERTICAL_PADDING:3,DIALOG_PADDING_FROM_WINDOW:p,MODAL:u,Dialog:m,PointerLeftDialogEvent:w,ClickOutsideDialogEvent:b,ForcedDialogClose:v});const D=new CSSStyleSheet;D.replaceSync("#close-button-container{height:0;width:100%}#close-button-container #close-button-right-aligner{position:relative;z-index:1;width:fit-content;left:100%;transform:translateX(-100%);padding-right:12px}#slot-container{margin-top:-14px;padding:0 12px}\n/*# sourceURL=iconDialog.css */\n");const x={close:"Close"},f=r.i18n.registerUIStrings("ui/components/dialogs/IconDialog.ts",x),C=r.i18n.getLocalizedString.bind(void 0,f);class S extends Event{static eventName="showdialog";constructor(){super(S.eventName)}}class P extends HTMLElement{static litTagName=s.literal`devtools-icon-dialog`;#t=this.attachShadow({mode:"open"});#e=this.#o.bind(this);#O=null;#l=null;#T=null;connectedCallback(){this.#t.adoptedStyleSheets=[D]}set data(t){this.#O=t,o.ScheduledRender.scheduleRender(this,this.#e)}#C(){if(!this.#l)throw new Error("Dialog not found");this.#l.setDialogVisible(!0),o.ScheduledRender.scheduleRender(this,this.#e),this.dispatchEvent(new S)}#S(){if(!this.#l)throw new Error("Dialog not found");this.#l.setDialogVisible(!1),o.ScheduledRender.scheduleRender(this,this.#e)}#o(){if(null===this.#O)throw new Error("IconDialog.data is not set");if(!o.ScheduledRender.isScheduledRender(this))throw new Error("IconDialog render was not scheduled");let t=s.nothing;this.#O.closeButton&&(t=s.html`
<div id='close-button-container'>
<div id='close-button-right-aligner'>
<${a.Icon.Icon.litTagName}
=${this.#S}
.data=${{iconName:"cross",color:"var(--icon-default-hover)",width:"16px",height:"16px"}}
jslog=${n.close().track({click:!0})}
title=${C(x.close)}
></${a.Icon.Icon.litTagName}>
</div>
</div>
`),s.render(s.html`
<${a.Icon.Icon.litTagName}
=${this.#C}
on-render=${o.Directives.nodeRenderedCallback((t=>{this.#T=t}))}
.data=${this.#O.iconData}
></${a.Icon.Icon.litTagName}>
<${m.litTagName}
=${this.#S}
.showConnector=${!0}
.origin=${()=>{if(!this.#T)throw new Error("Icon not found");return this.#T}}
.position=${this.#O.position}
.horizontalAlignment=${this.#O.horizontalAlignment}
.closeOnESC=${this.#O.closeOnESC}
.closeOnScroll=${this.#O.closeOnScroll}
on-render=${o.Directives.nodeRenderedCallback((t=>{this.#l=t}))}
>
${t}
<div id='slot-container'>
<slot></slot>
</div>
</${m.litTagName}>
`,this.#t,{host:this})}}customElements.define("devtools-icon-dialog",P);var E=Object.freeze({__proto__:null,ShowDialog:S,IconDialog:P});const $=new CSSStyleSheet;$.replaceSync(".keybinds-category-header{white-space:nowrap;padding:0 10px 20px;display:flex}.keybinds-category-header-text{line-height:24px;flex:auto;font-weight:bold}.keybinds-key{padding:0.1em 0.6em;border:1px solid var(--sys-color-neutral-outline);font-size:11px;background-color:var(--sys-color-neutral-container);color:var(--sys-color-on-surface);border-radius:3px;display:inline-block;margin:0 0.1em;text-shadow:0 1px 0 var(--sys-color-cdt-base-container);line-height:1.5;white-space:nowrap}.keybinds-list{list-style:none;margin:0;padding:0}.keybinds-list-item{line-height:30px;display:flex;padding:0 10px}.keybinds-list-text{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;user-select:none;color:var(--sys-color-on-surface);text-align:start;position:relative;margin-right:0}.keybinds-shortcut-separator{white-space:pre-wrap}.keybinds-action-name{flex:auto;padding-right:30px}.keybinds-shortcut{flex:none}.close-icon{width:12px;height:12px;padding-top:2px}\n/*# sourceURL=shortcutDialog.css */\n");const k={showShortcutTitle:"Show shortcuts",dialogTitle:"Keyboard shortcuts",close:"Close"},B=r.i18n.registerUIStrings("ui/components/dialogs/ShortcutDialog.ts",k),A=r.i18n.getLocalizedString.bind(void 0,B);class R extends Event{static eventName="showdialog";constructor(){super(R.eventName)}}class I extends HTMLElement{static litTagName=s.literal`devtools-shortcut-dialog`;#t=this.attachShadow({mode:"open"});#e=this.#o.bind(this);#l=null;#N=null;#z=[];#_=!1;connectedCallback(){this.#t.adoptedStyleSheets=[$]}set data(t){this.#z=t.shortcuts,t.open&&(this.#_=t.open),o.ScheduledRender.scheduleRender(this,this.#e)}#C(){if(!this.#l)throw new Error("Dialog not found");this.#l.setDialogVisible(!0),o.ScheduledRender.scheduleRender(this,this.#e),this.dispatchEvent(new R)}#S(t){if(!this.#l)throw new Error("Dialog not found");this.#l.setDialogVisible(!1),t&&t.stopImmediatePropagation(),o.ScheduledRender.scheduleRender(this,this.#e)}#o(){if(!o.ScheduledRender.isScheduledRender(this))throw new Error("Shortcut dialog render was not scheduled");s.render(s.html`
<${l.Button.Button.litTagName}
=${this.#C}
on-render=${o.Directives.nodeRenderedCallback((t=>{this.#N=t}))}
.data=${{variant:"toolbar",iconName:"help",title:A(k.showShortcutTitle)}}
></${l.Button.Button.litTagName}>
<${m.litTagName}
=${this.#S}
.showConnector=${!0}
.origin=${()=>{if(!this.#N)throw new Error("Button not found");return this.#N}}
.position=${"bottom"}
.horizontalAlignment=${"right"}
.jslogContext=${"shortcuts"}
on-render=${o.Directives.nodeRenderedCallback((t=>{this.#l=t}))}
>
<div class="keybinds-category-header">
<span class="keybinds-category-header-text">${A(k.dialogTitle)}</span>
<${l.Button.Button.litTagName}
=${this.#S}
class='close-icon'
.data=${{variant:"toolbar",iconName:"cross",title:A(k.close)}}
jslog=${n.close().track({click:!0})}
></${l.Button.Button.litTagName}>
</div>
<ul class="keybinds-list">
${this.#z.map((t=>s.html`
<li class="keybinds-list-item">
<div class="keybinds-action-name keybinds-list-text">${t.title}</div>
${t.bindings.map(((e,o)=>s.html`
<div class="keybinds-shortcut keybinds-list-text">
<span class="keybinds-key">${e}</span>
</div>
${t.bindings.at(o+1)?s.html`<span class="keybinds-shortcut-separator"> - </span>`:s.nothing}
`))}
</li>`))}
</ul>
</${m.litTagName}>
`,this.#t,{host:this}),this.#_&&(this.#C(),this.#_=!1)}}customElements.define("devtools-shortcut-dialog",I);var O=Object.freeze({__proto__:null,ShowDialog:R,ShortcutDialog:I});export{y as Dialog,E as IconDialog,O as ShortcutDialog};