@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 6.93 kB
JavaScript
import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as Platform from"../../core/platform/platform.js";import*as SDK from"../../core/sdk/sdk.js";import*as UI from"../../ui/legacy/legacy.js";import classesPaneWidgetStyles from"./classesPaneWidget.css.js";import{ElementsPanel}from"./ElementsPanel.js";const UIStrings={addNewClass:"Add new class",classesSAdded:"Classes {PH1} added",classSAdded:"Class {PH1} added",elementClasses:"Element Classes"},str_=i18n.i18n.registerUIStrings("panels/elements/ClassesPaneWidget.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class ClassesPaneWidget extends UI.Widget.Widget{input;classesContainer;prompt;mutatingNodes;pendingNodeClasses;updateNodeThrottler;previousTarget;constructor(){super(!0),this.contentElement.className="styles-element-classes-pane";const e=this.contentElement.createChild("div","title-container");this.input=e.createChild("div","new-class-input monospace"),this.setDefaultFocusedElement(this.input),this.classesContainer=this.contentElement.createChild("div","source-code"),this.classesContainer.classList.add("styles-element-classes-container"),this.prompt=new ClassNamePrompt(this.nodeClasses.bind(this)),this.prompt.setAutocompletionTimeout(0),this.prompt.renderAsBlock();const t=this.prompt.attach(this.input);this.prompt.setPlaceholder(i18nString(UIStrings.addNewClass)),this.prompt.addEventListener(UI.TextPrompt.Events.TextChanged,this.onTextChanged,this),t.addEventListener("keydown",this.onKeyDown.bind(this),!1),SDK.TargetManager.TargetManager.instance().addModelListener(SDK.DOMModel.DOMModel,SDK.DOMModel.Events.DOMMutated,this.onDOMMutated,this,{scoped:!0}),this.mutatingNodes=new Set,this.pendingNodeClasses=new Map,this.updateNodeThrottler=new Common.Throttler.Throttler(0),this.previousTarget=null,UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode,this.onSelectedNodeChanged,this)}splitTextIntoClasses(e){return e.split(/[,\s]/).map((e=>e.trim())).filter((e=>e.length))}onKeyDown(e){if("Enter"!==e.key&&!Platform.KeyboardUtilities.isEscKey(e))return;if("Enter"===e.key&&(e.consume(),this.prompt.acceptAutoComplete()))return;const t=e.target;let s=t.textContent;Platform.KeyboardUtilities.isEscKey(e)&&(Platform.StringUtilities.isWhitespace(s)||e.consume(!0),s=""),this.prompt.clearAutocomplete(),t.textContent="";const n=UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);if(!n)return;const i=this.splitTextIntoClasses(s);if(!i.length)return void this.installNodeClasses(n);for(const e of i)this.toggleClass(n,e,!0);const o=i.join(" "),a=i.length>1?i18nString(UIStrings.classesSAdded,{PH1:o}):i18nString(UIStrings.classSAdded,{PH1:o});UI.ARIAUtils.alert(a),this.installNodeClasses(n),this.update()}onTextChanged(){const e=UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);e&&this.installNodeClasses(e)}onDOMMutated(e){const t=e.data;this.mutatingNodes.has(t)||(cachedClassesMap.delete(t),this.update())}onSelectedNodeChanged(e){this.previousTarget&&this.prompt.text()&&(this.input.textContent="",this.installNodeClasses(this.previousTarget)),this.previousTarget=e.data,this.update()}wasShown(){super.wasShown(),this.update(),this.registerCSSFiles([classesPaneWidgetStyles])}update(){if(!this.isShowing())return;let e=UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);if(e&&(e=e.enclosingElementOrSelf()),this.classesContainer.removeChildren(),this.input.disabled=!e,!e)return;const t=this.nodeClasses(e),s=[...t.keys()];s.sort(Platform.StringUtilities.caseInsensetiveComparator);for(const e of s){const s=UI.UIUtils.CheckboxLabel.create(e,t.get(e));s.classList.add("monospace"),s.checkboxElement.addEventListener("click",this.onClick.bind(this,e),!1),this.classesContainer.appendChild(s)}}onClick(e,t){const s=UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);if(!s)return;const n=t.target.checked;this.toggleClass(s,e,n),this.installNodeClasses(s)}nodeClasses(e){let t=cachedClassesMap.get(e);if(!t){const s=(e.getAttribute("class")||"").split(/\s/);t=new Map;for(let e=0;e<s.length;++e){const n=s[e].trim();n.length&&t.set(n,!0)}cachedClassesMap.set(e,t)}return t}toggleClass(e,t,s){this.nodeClasses(e).set(t,s)}installNodeClasses(e){const t=this.nodeClasses(e),s=new Set;for(const e of t.keys())t.get(e)&&s.add(e);const n=this.splitTextIntoClasses(this.prompt.textWithCurrentSuggestion());for(const e of n)s.add(e);const i=[...s.values()].sort();this.pendingNodeClasses.set(e,i.join(" ")),this.updateNodeThrottler.schedule(this.flushPendingClasses.bind(this))}async flushPendingClasses(){const e=[];for(const s of this.pendingNodeClasses.keys()){this.mutatingNodes.add(s);const n=s.setAttributeValuePromise("class",this.pendingNodeClasses.get(s)).then(t.bind(this,s));e.push(n)}function t(e){this.mutatingNodes.delete(e)}this.pendingNodeClasses.clear(),await Promise.all(e)}}const cachedClassesMap=new WeakMap;let buttonProviderInstance;export class ButtonProvider{button;view;constructor(){this.button=new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.elementClasses),""),this.button.setText(".cls"),this.button.element.classList.add("monospace"),this.button.addEventListener(UI.Toolbar.ToolbarButton.Events.Click,this.clicked,this),this.view=new ClassesPaneWidget}static instance(e={forceNew:null}){const{forceNew:t}=e;return buttonProviderInstance&&!t||(buttonProviderInstance=new ButtonProvider),buttonProviderInstance}clicked(){ElementsPanel.instance().showToolbarPane(this.view.isShowing()?null:this.view,this.button)}item(){return this.button}}export class ClassNamePrompt extends UI.TextPrompt.TextPrompt{nodeClasses;selectedFrameId;classNamesPromise;constructor(e){super(),this.nodeClasses=e,this.initialize(this.buildClassNameCompletions.bind(this)," "),this.disableDefaultSuggestionForEmptyInput(),this.selectedFrameId="",this.classNamesPromise=null}async getClassNames(e){const t=[],s=new Set;this.selectedFrameId=e.frameId();const n=e.domModel().cssModel(),i=n.allStyleSheets();for(const e of i){if(e.frameId!==this.selectedFrameId)continue;const i=n.getClassNames(e.id).then((e=>{for(const t of e)s.add(t)}));t.push(i)}const o=e.ownerDocument.id,a=e.domModel().classNamesPromise(o).then((e=>{for(const t of e)s.add(t)}));return t.push(a),await Promise.all(t),[...s]}async buildClassNameCompletions(e,t,s){t&&!s||(this.classNamesPromise=null);const n=UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);if(!n||!t&&!s&&!e.trim())return[];this.classNamesPromise&&this.selectedFrameId===n.frameId()||(this.classNamesPromise=this.getClassNames(n));let i=await this.classNamesPromise;const o=this.nodeClasses(n);return i=i.filter((e=>!o.get(e))),"."===t[0]&&(i=i.map((e=>"."+e))),i.filter((e=>e.startsWith(t))).sort().map((e=>({text:e,title:void 0,subtitle:void 0,priority:void 0,isSecondary:void 0,subtitleRenderer:void 0,selectionRange:void 0,hideGhostText:void 0,iconElement:void 0})))}}