UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

29 lines 7.25 kB
import*as Platform from"../../../core/platform/platform.js";import*as LitHtml from"../../lit-html/lit-html.js";import*as CodeHighlighter from"../code_highlighter/code_highlighter.js";import*as ComponentHelpers from"../helpers/helpers.js";import*as Coordinator from"../render_coordinator/render_coordinator.js";import treeOutlineStyles from"./treeOutline.css.js";import{findNextNodeForTreeOutlineKeyboardNavigation,getNodeChildren,getPathToTreeNode,isExpandableNode,trackDOMNodeToTreeNode}from"./TreeOutlineUtils.js";const coordinator=Coordinator.RenderCoordinator.RenderCoordinator.instance();export function defaultRenderer(e){return LitHtml.html`${e.treeNodeData}`}export class ItemSelectedEvent extends Event{static eventName="itemselected";data;constructor(e){super(ItemSelectedEvent.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}export class ItemMouseOverEvent extends Event{static eventName="itemmouseover";data;constructor(e){super(ItemMouseOverEvent.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}export class ItemMouseOutEvent extends Event{static eventName="itemmouseout";data;constructor(e){super(ItemMouseOutEvent.eventName,{bubbles:!0,composed:!0}),this.data={node:e}}}export class TreeOutline extends HTMLElement{static litTagName=LitHtml.literal`devtools-tree-outline`;#e=this.attachShadow({mode:"open"});#t=[];#o=new Map;#r=new WeakMap;#d=!1;#n=null;#s=null;#i=(e,t)=>("string"!=typeof e.treeNodeData&&console.warn(`The default TreeOutline renderer simply stringifies its given value. You passed in ${JSON.stringify(e.treeNodeData,null,2)}. Consider providing a different defaultRenderer that can handle nodes of this type.`),LitHtml.html`${String(e.treeNodeData)}`);#a;#l=!1;#h=!1;#c=!1;static get observedAttributes(){return["nowrap","toplevelbordercolor"]}attributeChangedCallback(e,t,o){switch(e){case"nowrap":this.#p(o);break;case"toplevelbordercolor":this.#u(o)}}connectedCallback(){this.#u(this.getAttribute("toplevelbordercolor")),this.#p(this.getAttribute("nowrap")),this.#e.adoptedStyleSheets=[treeOutlineStyles,CodeHighlighter.Style.default]}get data(){return{tree:this.#t,defaultRenderer:this.#i}}set data(e){this.#i=e.defaultRenderer,this.#t=e.tree,this.#a=e.filter,this.#l=e.compact||!1,this.#d||(this.#s=this.#t[0]),this.#N()}async expandRecursively(e=2){await Promise.all(this.#t.map((t=>this.#m(t,0,e)))),await this.#N()}async collapseAllNodes(){this.#o.clear(),await this.#N()}async expandToAndSelectTreeNode(e){return this.expandToAndSelectTreeNodeId(e.id)}async expandToAndSelectTreeNodeId(e){const t=await getPathToTreeNode(this.#t,e);if(null===t)throw new Error(`Could not find node with id ${e} in the tree.`);t.forEach(((e,o)=>{o<t.length-1&&this.#f(e,!0)})),this.#n=e,await this.#N()}expandNodeIds(e){return e.forEach((e=>this.#o.set(e,!0))),this.#N()}focusNodeId(e){return this.#n=e,this.#N()}async collapseChildrenOfNode(e){const t=this.#r.get(e);t&&(await this.#g(t),await this.#N())}#p(e){ComponentHelpers.SetCSSProperty.set(this,"--override-key-whitespace-wrapping",null!==e?"nowrap":"initial")}#u(e){ComponentHelpers.SetCSSProperty.set(this,"--override-top-node-border",e?`1px solid ${e}`:"")}async#g(e){if(!isExpandableNode(e)||!this.#v(e))return;const t=await this.#E(e),o=Promise.all(t.map((e=>this.#g(e))));await o,this.#f(e,!1)}async#T(e,t){const o=await getNodeChildren(e),r=[];for(const e of o){const o=t(e.treeNodeData),d=this.#S(e)||e.id===this.#n,n=this.#o.get(e.id);if("SHOW"===o||d||n)r.push(e);else if("FLATTEN"===o&&isExpandableNode(e)){const o=await this.#T(e,t);r.push(...o)}}return r}async#E(e){const t=await getNodeChildren(e),o=this.#a;if(!o)return t;const r=await this.#T(e,o);return r.length?r:t}#f(e,t){this.#o.set(e.id,t)}#v(e){return this.#o.get(e.id)||!1}async#m(e,t,o){if(!isExpandableNode(e))return;if(this.#f(e,!0),t===o||!isExpandableNode(e))return;const r=await this.#E(e);await Promise.all(r.map((e=>this.#m(e,t+1,o))))}#w(e){return t=>{t.stopPropagation(),isExpandableNode(e)&&(this.#f(e,!this.#v(e)),this.#N())}}#x(e){e.stopPropagation();const t=null!==this.getAttribute("clickabletitle"),o=e.currentTarget,r=this.#r.get(o);t&&r&&isExpandableNode(r)&&this.#f(r,!this.#v(r)),this.#y(o)}async#y(e){const t=this.#r.get(e);t&&(this.#s=t,await this.#N(),this.dispatchEvent(new ItemSelectedEvent(t)),coordinator.write("DOMNode focus",(()=>{e.focus()})))}#b(e){if("Home"===e){const e=this.#e.querySelector('ul[role="tree"] > li[role="treeitem"]');e&&this.#y(e)}else if("End"===e){const e=this.#e.querySelectorAll('li[role="treeitem"]'),t=e[e.length-1];t&&this.#y(t)}}async#C(e,t){const o=this.#r.get(t);if(!o)return;const r=findNextNodeForTreeOutlineKeyboardNavigation({currentDOMNode:t,currentTreeNode:o,direction:e,setNodeExpandedState:(e,t)=>this.#f(e,t)});await this.#y(r)}#I(e){const t=this.#r.get(e);if(t&&isExpandableNode(t)){const e=this.#v(t);this.#f(t,!e),this.#N()}}async#M(e){if(!(e.target instanceof HTMLLIElement))throw new Error("event.target was not an <li> element");"Home"===e.key||"End"===e.key?(e.preventDefault(),this.#b(e.key)):Platform.KeyboardUtilities.keyIsArrowKey(e.key)?(e.preventDefault(),await this.#C(e.key,e.target)):"Enter"!==e.key&&" "!==e.key||(e.preventDefault(),this.#I(e.target))}#k(e){this.#n=null,this.#y(e)}#S(e){return!!this.#s&&e.id===this.#s.id}#D(e,{depth:t,setSize:o,positionInSet:r}){let d;const n=this.#v(e);if(isExpandableNode(e)&&n){const o=this.#E(e).then((e=>e.map(((o,r)=>this.#D(o,{depth:t+1,setSize:e.length,positionInSet:r})))));d=LitHtml.html`<ul role="group">${LitHtml.Directives.until(o)}</ul>`}else d=LitHtml.nothing;const s=this.#S(e)?0:-1,i=LitHtml.Directives.classMap({expanded:isExpandableNode(e)&&n,parent:isExpandableNode(e),selected:this.#S(e),"is-top-level":0===t,compact:this.#l}),a=LitHtml.Directives.ifDefined(isExpandableNode(e)?String(n):void 0);let l;return l=e.renderer?e.renderer(e,{isExpanded:n}):this.#i(e,{isExpanded:n}),LitHtml.html` <li role="treeitem" tabindex=${s} aria-setsize=${o} aria-expanded=${a} aria-level=${t+1} aria-posinset=${r+1} class=${i} @click=${this.#x} track-dom-node-to-tree-node=${trackDOMNodeToTreeNode(this.#r,e)} on-render=${ComponentHelpers.Directives.nodeRenderedCallback((t=>{t instanceof HTMLLIElement&&this.#n&&e.id===this.#n&&this.#k(t)}))} > <span class="arrow-and-key-wrapper" @mouseover=${()=>{this.dispatchEvent(new ItemMouseOverEvent(e))}} @mouseout=${()=>{this.dispatchEvent(new ItemMouseOutEvent(e))}} > <span class="arrow-icon" @click=${this.#w(e)}> </span> <span class="tree-node-key" data-node-key=${e.treeNodeData}>${l}</span> </span> ${d} </li> `}async#N(){if(!this.#h)return this.#h=!0,await coordinator.write("TreeOutline render",(()=>{LitHtml.render(LitHtml.html` <div class="wrapping-container"> <ul role="tree" @keydown=${this.#M}> ${this.#t.map(((e,t)=>this.#D(e,{depth:0,setSize:this.#t.length,positionInSet:t})))} </ul> </div> `,this.#e,{host:this})})),this.#d=!0,this.#h=!1,this.#c?(this.#c=!1,this.#N()):void 0;this.#c=!0}}ComponentHelpers.CustomElements.defineComponent("devtools-tree-outline",TreeOutline);