14 lines
26 KiB
JavaScript
14 lines
26 KiB
JavaScript
/*
|
|
* This file is part of the TYPO3 CMS project.
|
|
*
|
|
* It is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License, either version 2
|
|
* of the License, or any later version.
|
|
*
|
|
* For the full copyright and license information, please read the
|
|
* LICENSE.txt file that was distributed with this source code.
|
|
*
|
|
* The TYPO3 project - inspiring people to share!
|
|
*/
|
|
import{LitElement as x,html as a,nothing as N}from"lit";import{property as C,state as p,query as $}from"lit/decorators.js";import{repeat as F}from"lit/directives/repeat.js";import{styleMap as b}from"lit/directives/style-map.js";import{ifDefined as D}from"lit/directives/if-defined.js";import{TreeNodePositionEnum as u,TreeNodeCommandEnum as h}from"@typo3/backend/tree/tree-node.js";import w from"@typo3/core/ajax/ajax-request.js";import P from"@typo3/backend/notification.js";import{KeyTypesEnum as l}from"@typo3/backend/enum/key-types.js";import"@typo3/backend/element/icon-element.js";import E from"@typo3/backend/storage/client.js";import{DataTransferTypes as m}from"@typo3/backend/enum/data-transfer-types.js";import k from"@typo3/backend/severity.js";import S from"~labels/core.misc";import R from"~labels/backend.layout";import{openPageWizardModal as O}from"@typo3/backend/page-wizard/helper/wizard-helper.js";var f=function(_,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(_,e,t,r);else for(var n=_.length-1;n>=0;n--)(o=_[n])&&(i=(s<3?o(i):s>3?o(e,t,i):o(e,t))||i);return s>3&&i&&Object.defineProperty(e,t,i),i};class y{constructor(e){this.treeNodes=e,this.updateIndexes()}get length(){return this.treeNodes.length}toArray(){return this.treeNodes}splice(e,t,...r){this.treeNodes.splice(e,t,...r),this.updateIndexes()}getNodeByTreeIdentifier(e){const t=this.treeIdentifierIndex[e]??null;return this.treeNodes[t]??null}updateIndexes(){this.treeIdentifierIndex=Object.fromEntries(this.treeNodes.map((e,t)=>[e.__treeIdentifier,t]))}}class T extends CustomEvent{static{this.eventName="typo3:tree:filter-applied"}constructor(e,t){super(T.eventName,{detail:{searchTerm:e,resultCount:t},bubbles:!0,composed:!0})}}class v extends Event{static{this.eventName="typo3:tree:filter-reset"}constructor(){super(v.eventName,{bubbles:!0,composed:!0})}}class c extends x{constructor(){super(...arguments),this.setup=null,this.settings={showIcons:!1,width:300,dataUrl:"",filterUrl:"",defaultProperties:{},expandUpToLevel:null,actions:[]},this.nodeMap=new y([]),this.currentScrollPosition=0,this.currentVisibleHeight=0,this.searchTerm=null,this.searchResults=0,this.loading=!1,this.hoveredNode=null,this.nodeDragAllowed=!1,this.isOverRoot=!1,this.nodeDragPosition=null,this.nodeDragMode=null,this.draggingNode=null,this.nodeHeight=32,this.indentWidth=20,this.displayNodes=[],this.focusedNode=null,this.lastFocusedNode=null,this.editingNode=null,this.openNodeTimeout={targetNode:null,timeout:null},this.unfilteredNodes="",this.muteErrorNotifications=!1,this.networkErrorTitle=S.get("tree_networkError"),this.networkErrorMessage=S.get("tree_networkErrorDescription"),this.allowNodeEdit=!1,this.allowNodeDrag=!1,this.allowNodeSorting=!1,this.currentFilterRequest=null,this.__loadPromise=new Promise(e=>this.__loadFinished=e),this.lastRenderScrollPosition=null}get loadComplete(){return this.__loadPromise}get nodes(){return this.nodeMap.toArray()}set nodes(e){this.nodeMap=new y(e)}getNodeFromElement(e){return e===null||!("treeId"in e.dataset)?null:this.getNodeByTreeIdentifier(e.dataset.treeId)}getElementFromNode(e){return this.querySelector('[data-tree-id="'+this.getNodeTreeIdentifier(e)+'"]')}hideChildren(e){e.__expanded=!1,this.saveNodeStatus(e),this.dispatchEvent(new CustomEvent("typo3:tree:expand-toggle",{detail:{node:e}}))}async showChildren(e){e.__expanded=!0,await this.loadChildren(e),this.saveNodeStatus(e),this.dispatchEvent(new CustomEvent("typo3:tree:expand-toggle",{detail:{node:e}}))}getDataUrl(e=null){return e===null?this.settings.dataUrl:this.settings.dataUrl+"&parent="+e.identifier+"&depth="+e.depth}getFilterUrl(){return this.settings.filterUrl+"&q="+this.searchTerm}async loadData(){this.loading=!0,this.nodeMap=new y(this.prepareNodes(await this.fetchData())),this.__loadFinished(),this.__loadPromise=new Promise(e=>this.__loadFinished=e),this.loading=!1}async fetchData(e=null){try{let r=await(await new w(this.getDataUrl(e)).get({cache:"no-cache"})).resolve();return Array.isArray(r)?(e!==null&&(r=r.filter(i=>i.identifier!==e.identifier),r.unshift(e)),r=this.enhanceNodes(r),e!==null&&r.shift(),(await Promise.all(r.map(async i=>{const o=i.__parents.join("_"),n=r.find(g=>g.__treeIdentifier===o)||null,d=n===null||n.__expanded;if(!i.loaded&&i.hasChildren&&i.__expanded&&d){const g=await this.fetchData(i);return i.loaded=!0,[i,...g]}else return[i]}))).flat()):[]}catch(t){return this.errorNotification(t),[]}}async loadChildren(e){try{if(e.loaded){await Promise.all(this.nodes.filter(i=>i.__parents.join("_")===e.__treeIdentifier&&!i.loaded&&i.hasChildren&&i.__expanded).map(i=>this.loadChildren(i)));return}e.__loading=!0;const t=this.prepareNodes(await this.fetchData(e)),r=this.nodes.indexOf(e)+1;let s=0;for(let i=r;i<this.nodes.length&&!(this.nodes[i].depth<=e.depth);++i)s++;this.nodeMap.splice(r,s,...t),e.__loading=!1,e.loaded=!0}catch(t){throw this.errorNotification(t),e.__loading=!1,t}}getIdentifier(){return this.id??this.setup.id}getLocalStorageIdentifier(){return"tree-state-"+this.getIdentifier()}getNodeStatus(e){return(JSON.parse(E.get(this.getLocalStorageIdentifier()))??{})[e.__treeIdentifier]??{expanded:!1}}saveNodeStatus(e){const t=JSON.parse(E.get(this.getLocalStorageIdentifier()))??{};t[e.__treeIdentifier]={expanded:e.__expanded},E.set(this.getLocalStorageIdentifier(),JSON.stringify(t))}refreshOrFilterTree(){this.searchTerm!==""?this.filter(this.searchTerm):this.loadData()}selectFirstNode(){const e=this.getFirstNode();this.selectNode(e,!0),this.focusNode(e)}selectNode(e,t=!0){this.isNodeSelectable(e)&&(this.resetSelectedNodes(),e.checked=!0,this.dispatchEvent(new CustomEvent("typo3:tree:node-selected",{detail:{node:e,propagate:t},bubbles:!0,composed:!0})))}async focusNode(e){this.lastFocusedNode=this.focusedNode,this.focusedNode=e,this.requestUpdate();const t=this.getElementFromNode(this.focusedNode);t?t.focus():this.updateComplete.then(()=>{this.getElementFromNode(this.focusedNode)?.focus()})}async editNode(e){this.isNodeEditable(e)&&(this.editingNode=e,this.requestUpdate(),this.updateComplete.then(()=>{const t=this.getElementFromNode(this.editingNode)?.querySelector(".node-edit");t&&(t.focus(),t.select())}))}scrollNodeIntoViewIfNeeded(e){const t=e.__y+this.nodeHeight/2,r=this.root.scrollTop,s=r+this.root.clientHeight,i=t-this.root.clientHeight/2;(t<r||t>s)&&(this.root.scrollTop=i)}async deleteNode(e){if(!e.deletable){console.error("The Node cannot be deleted.");return}this.handleNodeDelete(e)}async moveNode(e,t,r){this.handleNodeMove(e,t,r)}async addNode(e,t,r){let s=this.nodes.indexOf(t);const i=r===u.INSIDE?t:this.getParentNode(t),o=this.enhanceNodes([i,{...e,depth:i?i.depth+1:0}]).pop();if(i&&(i.hasChildren&&!i.__expanded&&await this.showChildren(i),i.hasChildren||(i.hasChildren=!0,i.__expanded=!0)),r===u.INSIDE)s+=1;else if(r===u.AFTER){const n=t.depth;let d=s+1;for(;d<this.nodes.length&&this.nodes[d].depth>n;)d++;s=d}this.nodeMap.splice(s,0,o),this.handleNodeAdd(o,t,r)}async removeNode(e){const t=this.nodes.indexOf(e),r=this.getParentNode(e);t>-1&&this.nodeMap.splice(t,1),this.requestUpdate(),this.updateComplete.then(()=>{r?.__expanded&&r.hasChildren&&this.getNodeChildren(r).length===0&&(r.hasChildren=!1,r.__expanded=!1)})}filter(e){typeof e=="string"&&(this.searchTerm=e),this.searchTerm&&this.settings.filterUrl?(this.loading=!0,this.currentFilterRequest?.abort(),this.currentFilterRequest=new w(this.getFilterUrl()),this.currentFilterRequest.get({cache:"no-cache"}).then(t=>t.resolve()).then(t=>{const r=Array.isArray(t)?t:[];this.searchResults=r.length,r.length>0&&(this.unfilteredNodes===""&&(this.unfilteredNodes=JSON.stringify(this.nodes)),this.nodeMap=new y(this.enhanceNodes(r)),this.searchResults=r.length)}).catch(t=>{if(!(t instanceof DOMException&&t.name==="AbortError"))throw this.errorNotification(t),t}).then(()=>{this.loading=!1,this.currentFilterRequest=null,this.dispatchEvent(new T(this.searchTerm,this.searchResults))})):this.resetFilter().then(()=>{this.loading=!1,this.dispatchEvent(new v)})}async resetFilter(){if(this.searchTerm="",this.searchResults=0,this.unfilteredNodes.length>0){const e=this.getSelectedNodes()[0];if(typeof e>"u"){await this.loadData();return}this.nodeMap=new y(this.enhanceNodes(JSON.parse(this.unfilteredNodes))),this.unfilteredNodes="";const t=this.getNodeByTreeIdentifier(e.__treeIdentifier);t?this.selectNode(t,!1):await this.loadData()}else await this.loadData()}errorNotification(e=null){if(!this.muteErrorNotifications)if(Array.isArray(e))e.forEach(t=>{P.error(t.title,t.message)});else{let t=this.networkErrorTitle;e&&e.target&&(e.target.status||e.target.statusText)&&(t+=" - "+(e.target.status||"")+" "+(e.target.statusText||"")),P.error(t,this.networkErrorMessage)}}getSelectedNodes(){return this.nodes.filter(e=>e.checked)}getNodeByTreeIdentifier(e){return this.nodeMap.getNodeByTreeIdentifier(e)}getNodeDragStatusIcon(){return this.nodeDragMode===h.DELETE?"actions-delete":this.nodeDragMode===h.NEW?"actions-add":this.nodeDragPosition===u.BEFORE?"apps-pagetree-drag-move-above":this.nodeDragPosition===u.INSIDE?"apps-pagetree-drag-move-into":this.nodeDragPosition===u.AFTER?"apps-pagetree-drag-move-below":"actions-ban"}async expandParents(e){for(const t of e){const r=this.nodes.find(s=>s.identifier===t.toString());if(!r)return;r.__expanded||await this.showChildren(r)}}async expandNodeParents(e){await this.expandParents(e.__parents)}prepareNodes(e){const t=new CustomEvent("typo3:tree:nodes-prepared",{detail:{nodes:e},bubbles:!1});return this.dispatchEvent(t),t.detail.nodes}enhanceNodes(e){const t=e.reduce((s,i)=>{if(i?.__processed===!0)return[...s,i];i=Object.assign({},this.settings.defaultProperties,i),i.__parents=[];const o=i.depth>0?s.findLast(d=>d.depth<i.depth):null;o&&(i.__parents=[...o.__parents,o.identifier]),i.__treeIdentifier=i.identifier,i.__loading=!1,i.__treeParents=[],o&&(i.__treeIdentifier=o.__treeIdentifier+"_"+i.__treeIdentifier,i.__treeParents=[...o.__treeParents,o.__treeIdentifier]),this.searchTerm?i.__expanded=i.loaded&&i.hasChildren:i.hasChildren?i.__expanded=this.settings.expandUpToLevel!==null?i.depth<this.settings.expandUpToLevel:!!this.getNodeStatus(i).expanded:i.__expanded=!1,i.__processed=!0;const n=this;return[...s,new Proxy(i,{set(d,g,I){return d[g]!==I&&(d[g]=I,n.requestUpdate()),!0}})]},[]);return t.filter(s=>s.depth===0).length===1&&(t[0].__expanded=!0),t}createRenderRoot(){return this}shouldUpdate(e){return!(e.size===1&&e.has("currentScrollPosition")&&this.lastRenderScrollPosition!==null&&Math.abs(this.currentScrollPosition-this.lastRenderScrollPosition)/this.nodeHeight<20)}render(){const e=this.loading?a`<div class=nodes-loader><div class=nodes-loader-inner><typo3-backend-icon identifier=spinner-circle size=medium></typo3-backend-icon></div></div>`:N;return a`<div class=nodes-container>${e}<div class=nodes-root @scroll=${t=>{this.currentScrollPosition=t.currentTarget.scrollTop}} @mouseover=${()=>this.isOverRoot=!0} @mouseout=${()=>this.isOverRoot=!1} @keydown=${t=>this.handleKeyboardInteraction(t)}>${this.renderVisibleNodes()}</div></div>`}renderVisibleNodes(){this.displayNodes=this.nodes.filter(s=>s.__hidden!==!0&&!s.__treeParents.some(i=>this.getNodeByTreeIdentifier(i).__expanded===!1)),this.displayNodes.forEach((s,i)=>{s.__x=s.depth*this.indentWidth,s.__y=i*this.nodeHeight}),this.lastRenderScrollPosition=this.currentScrollPosition;const e=Math.ceil(this.currentVisibleHeight/this.nodeHeight),t=Math.floor(this.currentScrollPosition/this.nodeHeight),r=this.displayNodes.filter((s,i)=>this.getFirstNode()===s||this.focusedNode===s||this.lastFocusedNode===s?!0:i+40>=t&&i-40<t+e);return a`<div class=nodes-list role=tree style=${b({height:this.displayNodes.length*this.nodeHeight+"px"})}>${F(r,s=>this.getNodeTreeIdentifier(s),s=>a`<div class=${this.getNodeClasses(s).join(" ")} role=treeitem draggable=true title=${this.getNodeTitle(s)} aria-owns=${D(s.hasChildren?"group-identifier-"+this.getNodeIdentifier(s):null)} aria-expanded=${D(s.hasChildren?s.__expanded?"true":"false":null)} aria-level=${this.getNodeDepth(s)+1} aria-setsize=${this.getNodeSetsize(s)} aria-posinset=${this.getNodePositionInSet(s)} data-id=${this.getNodeIdentifier(s)} data-tree-id=${this.getNodeTreeIdentifier(s)} style=top:${s.__y+"px"};height:${this.nodeHeight+"px"} tabindex=${this.getNodeTabindex(s)} @dragover=${i=>{this.handleNodeDragOver(i)}} @dragstart=${i=>{this.handleNodeDragStart(i,s)}} @dragleave=${i=>{this.handleNodeDragLeave(i)}} @dragend=${i=>{this.handleNodeDragEnd(i)}} @drop=${i=>{this.handleNodeDrop(i)}} @click=${i=>{this.handleNodeClick(i,s)}} @dblclick=${i=>{this.handleNodeDoubleClick(i,s)}} @focusin=${()=>{this.focusedNode=s}} @focusout=${()=>{this.focusedNode===s&&(this.lastFocusedNode=s,this.focusedNode=null)}} @contextmenu=${i=>{i.preventDefault(),i.stopPropagation(),this.dispatchEvent(new CustomEvent("typo3:tree:node-context",{detail:{node:s,originalEvent:i}}))}}>${this.createNodeLabel(s)} ${this.createNodeGuides(s)} ${this.createNodeLoader(s)||this.createNodeToggle(s)||N} ${this.createNodeContent(s)} ${this.createNodeStatusInformation(s)} ${this.createNodeDeleteDropZone(s)}</div>`)}</div>`}async firstUpdated(){new ResizeObserver(t=>{for(const r of t)r.target===this.root&&(this.currentVisibleHeight=r.target.getBoundingClientRect().height)}).observe(this.root),Object.assign(this.settings,this.setup||{}),this.registerUnloadHandler(),await this.loadData(),this.dispatchEvent(new Event("tree:initialized"))}resetSelectedNodes(){this.getSelectedNodes().forEach(e=>{e.checked===!0&&(e.checked=!1)})}isNodeSelectable(e){return!0}isNodeEditable(e){return e.editable&&this.allowNodeEdit}handleNodeClick(e,t){e.detail===1&&(e.preventDefault(),e.stopPropagation(),this.editingNode!==t&&this.selectNode(t,!0))}handleNodeDoubleClick(e,t){e.preventDefault(),e.stopPropagation(),this.editingNode!==t&&this.editNode(t)}cleanDrag(){this.querySelectorAll(".node").forEach(function(t){t.classList.remove("node-dragging-before"),t.classList.remove("node-dragging-after"),t.classList.remove("node-hover")})}getNodeFromDragEvent(e){const t=e.target;return this.getNodeFromElement(t.closest("[data-tree-id]"))}getTooltipDescription(e){return"ID: "+e.identifier}handleNodeDragStart(e,t){if(this.allowNodeDrag===!1||t.depth===0){e.preventDefault();return}this.draggingNode=t,this.requestUpdate(),e.dataTransfer.clearData();const r={statusIconIdentifier:this.getNodeDragStatusIcon(),tooltipIconIdentifier:t.icon,tooltipLabel:t.name,tooltipDescription:this.getTooltipDescription(t)};e.dataTransfer.setData(m.dragTooltip,JSON.stringify(r)),this.createDataTransferItemsFromNode(t).forEach(({data:s,type:i})=>e.dataTransfer.items.add(s,i)),e.dataTransfer.effectAllowed="move"}handleNodeDragOver(e){if(!e.dataTransfer.types.includes(m.treenode)&&!e.dataTransfer.types.includes(m.newTreenode))return!1;const t=e.target,r=this.getNodeFromDragEvent(e);if(r===null||this.draggingNode===null)return!1;this.cleanDrag(),this.refreshDragToolTip(),this.nodeDragMode=null,this.nodeDragPosition=null;const s=this.getElementFromNode(r);if(s.classList.add("node-hover"),r.hasChildren&&!r.__expanded?this.openNodeTimeout.targetNode!=r&&(this.openNodeTimeout.targetNode=r,clearTimeout(this.openNodeTimeout.timeout),this.openNodeTimeout.timeout=setTimeout(()=>{this.showChildren(this.openNodeTimeout.targetNode),this.openNodeTimeout.targetNode=null,this.openNodeTimeout.timeout=null},1e3)):(clearTimeout(this.openNodeTimeout.timeout),this.openNodeTimeout.targetNode=null,this.openNodeTimeout.timeout=null),this.draggingNode==r)return t.dataset.treeDropzone==="delete"?(this.nodeDragMode=h.DELETE,e.preventDefault(),this.refreshDragToolTip(),!0):(this.refreshDragToolTip(),!0);if(r.__parents.includes(this.draggingNode.identifier))return this.refreshDragToolTip(),!0;if(this.nodeDragMode=h.MOVE,e.dataTransfer.types.includes(m.newTreenode)&&(this.nodeDragMode=h.NEW),this.nodeDragPosition=u.INSIDE,r.depth===0||this.allowNodeSorting===!1)return this.refreshDragToolTip(),e.preventDefault(),!0;const o=this.getElementFromNode(r).getBoundingClientRect(),n=e.clientY-o.y;return n<6?(this.nodeDragPosition=u.BEFORE,s.classList.add("node-dragging-before")):this.nodeHeight-n<6&&r.hasChildren===!1&&r.__expanded===!1&&(this.nodeDragPosition=u.AFTER,s.classList.add("node-dragging-after")),this.refreshDragToolTip(),e.preventDefault(),!0}handleNodeDragLeave(e){this.draggingNode!==null&&this.cleanDrag()}handleNodeDragEnd(e){this.cleanDrag(),this.draggingNode=null,this.requestUpdate()}handleNodeDrop(e){if(this.cleanDrag(),e.dataTransfer.types.includes(m.treenode)){e.preventDefault();const t=e.dataTransfer.getData(m.treenode),r=this.getNodeByTreeIdentifier(t);this.nodeDragMode===h.DELETE&&this.deleteNode(r);const s=this.getNodeFromDragEvent(e);return s===null?!1:(this.nodeDragMode===h.MOVE&&this.moveNode(r,s,this.nodeDragPosition),this.nodeDragMode=null,this.nodeDragPosition=null,!0)}if(e.dataTransfer.types.includes(m.newTreenode)){e.preventDefault();let t=this.getNodeFromDragEvent(e);if(t===null)return!1;const r=JSON.parse(e.dataTransfer.getData(m.newTreenode));let s="inside";if(this.nodeDragPosition===u.AFTER)s="after";else if(this.nodeDragPosition===u.BEFORE){const i=this.getPreviousNode(t);s=i.depth==t.depth?"after":"inside",t=i}return O({doktype:String(r.doktype),positionData:{pageUid:parseInt(t.identifier,10),insertPosition:s}}),this.nodeDragMode=null,this.nodeDragPosition=null,!0}return!1}refreshDragToolTip(){top.document.dispatchEvent(new CustomEvent("typo3:drag-tooltip:metadata-update",{detail:{statusIconIdentifier:this.getNodeDragStatusIcon()}}))}createNodeLabel(e){const t=this.getNodeLabels(e);if(t.length===0)return a`${N}`;const s={backgroundColor:t[0].color};return a`<span class=node-label style=${b(s)}></span>`}createNodeGuides(e){const t=e.__treeParents.map(r=>{const s=this.getNodeByTreeIdentifier(r);let i="none";return this.getNodeSetsize(s)!==this.getNodePositionInSet(s)&&(i="line"),a`<div class="node-treeline node-treeline--${i}" data-origin=${this.getNodeTreeIdentifier(s)} data-nodesize=${this.getNodeSetsize(s)} data-position=${this.getNodePositionInSet(s)}></div>`});return this.getNodeSetsize(e)===this.getNodePositionInSet(e)?t.push(a`<div class="node-treeline node-treeline--last" data-origin=${this.getNodeTreeIdentifier(e)}></div>`):t.push(a`<div class="node-treeline node-treeline--connect" data-origin=${this.getNodeTreeIdentifier(e)}></div>`),a`<div class=node-treelines>${t}</div>`}createNodeLoader(e){return e.__loading===!0?a`<span class=node-loading> <typo3-backend-icon identifier=spinner-circle size=small></typo3-backend-icon> </span>`:null}createNodeToggle(e){return e.hasChildren===!0?a`<span class=node-toggle @click=${t=>{t.preventDefault(),t.stopImmediatePropagation(),this.handleNodeToggle(e)}}> <typo3-backend-icon identifier=${e.__expanded?"actions-chevron-down":"actions-chevron-end"} size=small></typo3-backend-icon> </span>`:null}createNodeContent(e){return a`<div class=node-content>${this.createNodeContentIcon(e)} ${this.editingNode===e?this.createNodeForm(e):this.createNodeContentLabel(e)} ${this.createNodeContentAction(e)}</div>`}createNodeContentIcon(e){return this.settings.showIcons?a`<span class=node-icon @click=${t=>{t.preventDefault(),t.stopImmediatePropagation(),this.dispatchEvent(new CustomEvent("typo3:tree:node-context",{detail:{node:e,originalEvent:t}}))}} @dblclick=${t=>{t.preventDefault(),t.stopImmediatePropagation()}}> <typo3-backend-icon identifier=${e.icon} overlay=${e.overlayIcon} size=small></typo3-backend-icon> </span>`:a`${N}`}createNodeContentLabel(e){const t=(e.prefix||"")+e.name+(e.suffix||"");let r=t;if(this.searchTerm&&this.searchResults<=100&&(this.searchTerm.length>1||/\d/.test(this.searchTerm))){const s=new RegExp(`(${this.searchTerm.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")})`,"gi"),i=t.split(s);i.length>1&&(r=i.map((o,n)=>n%2===1?a`<span class=node-highlight-text>${o}</span>`:o))}return a`<div class=node-contentlabel><div class=node-name>${r}</div>${e.note?a`<div class=node-note>${e.note}</div>`:N}</div>`}createNodeStatusInformation(e){const t=this.getNodeStatusInformation(e);if(t.length===0)return a`${N}`;const r=t[0],s=k.getCssClass(r.severity),i=r.icon!==""?r.icon:"actions-dot",o=r.overlayIcon!==""?r.overlayIcon:void 0;return a`<span class="node-information node-information-${s}"> <typo3-backend-icon identifier=${i} overlay=${D(o)} size=small></typo3-backend-icon> </span>`}createNodeDeleteDropZone(e){return this.draggingNode===e&&e.deletable?a`<div class=node-dropzone-delete data-tree-dropzone=delete><typo3-backend-icon identifier=actions-delete size=small></typo3-backend-icon>${R.get("deleteItem")}</div>`:a`${N}`}createNodeForm(e){const t=e.identifier.startsWith("NEW")?h.NEW:h.EDIT;return a`<input class=node-edit @click=${i=>{i.stopImmediatePropagation()}} @blur=${i=>{if(this.editingNode!==null){this.editingNode=null;const n=i.target.value.trim();n!==e.name&&n!==""?this.handleNodeEdit(e,n):t===h.NEW&&this.removeNode(e),this.requestUpdate()}}} @keydown=${i=>{const o=i.key;if([l.ENTER,l.TAB].includes(o)){const d=i.target.value.trim();this.editingNode=null,this.requestUpdate(),d!==e.name&&d!==""?(this.handleNodeEdit(e,d),this.focusNode(e)):t===h.NEW&&d===""?this.removeNode(e):this.focusNode(e)}else[l.ESCAPE].includes(o)&&(this.editingNode=null,this.requestUpdate(),t===h.NEW?this.removeNode(e):this.focusNode(e))}} value=${e.name}>`}async handleNodeEdit(e,t){console.error("The function Tree->handleNodeEdit is not implemented.")}handleNodeDelete(e){console.error("The function Tree->handleNodeDelete is not implemented.")}handleNodeMove(e,t,r){console.error("The function Tree->handleNodeMove is not implemented.")}async handleNodeAdd(e,t,r){console.error("The function Tree->handleNodeAdd is not implemented.")}createNodeContentAction(e){return a`${N}`}createDataTransferItemsFromNode(e){throw new Error("The function Tree->createDataTransferItemFromNode is not implemented.")}getNodeIdentifier(e){return e.identifier}getNodeTreeIdentifier(e){return e.__treeIdentifier}getNodeParentTreeIdentifier(e){return e.__parents.join("_")}getNodeClasses(e){const t=["node"];return e.checked&&t.push("node-selected"),this.draggingNode===e&&t.push("node-dragging"),t}getNodeLabels(e){let t=e.labels;if(t?.length>0)return t=t.sort((s,i)=>i.priority-s.priority),t;const r=this.getParentNode(e);return r===null?[]:this.getNodeLabels(r).filter(s=>s.inheritByChildren)}getNodeStatusInformation(e){return e.statusInformation?.length?e.statusInformation.sort((r,s)=>r.severity!==s.severity?s.severity-r.severity:s.priority-r.priority):[]}getNodeDepth(e){return e.depth}getNodeTabindex(e){return this.focusedNode?this.focusedNode===e?0:-1:this.lastFocusedNode?this.lastFocusedNode===e?0:-1:this.getFirstNode()===e?0:-1}getNodeChildren(e){return e?.hasChildren?this.displayNodes.filter(t=>e===this.getParentNode(t)):[]}getNodeSetsize(e){if(e.depth===0)return this.displayNodes.filter(s=>s.depth===0).length;const t=this.getParentNode(e);return this.getNodeChildren(t).length}getNodePositionInSet(e){const t=this.getParentNode(e);let r=[];return e.depth===0?r=this.displayNodes.filter(s=>s.depth===0):t!==null&&(r=this.getNodeChildren(t)),r.indexOf(e)+1}getFirstNode(){return this.displayNodes.length?this.displayNodes[0]:null}getPreviousNode(e){const r=this.displayNodes.indexOf(e)-1;return this.displayNodes[r]?this.displayNodes[r]:null}getNextNode(e){const r=this.displayNodes.indexOf(e)+1;return this.displayNodes[r]?this.displayNodes[r]:null}getLastNode(){return this.displayNodes.length?this.displayNodes[this.displayNodes.length-1]:null}getParentNode(e){return e.__parents.length?this.getNodeByTreeIdentifier(this.getNodeParentTreeIdentifier(e)):null}getNodeTitle(e){let t=e.tooltip?e.tooltip:"uid="+e.identifier+" "+e.name;const r=this.getNodeLabels(e);r.length&&(t+="; "+r.map(i=>i.label).join("; "));const s=this.getNodeStatusInformation(e);return s.length&&(t+="; "+s.map(i=>i.label).join("; ")),t}handleNodeToggle(e){e.__expanded?this.hideChildren(e):this.showChildren(e)}handleKeyboardInteraction(e){if(this.editingNode!==null||[l.ENTER,l.SPACE,l.END,l.HOME,l.LEFT,l.UP,l.RIGHT,l.DOWN].includes(e.key)===!1)return;const r=e.target,s=this.getNodeFromElement(r);if(s===null)return;const i=this.getParentNode(s),o=this.getFirstNode(),n=this.getPreviousNode(s),d=this.getNextNode(s),g=this.getLastNode();switch(e.preventDefault(),e.key){case l.HOME:o!==null&&(this.scrollNodeIntoVisibleArea(o),this.focusNode(o));break;case l.END:g!==null&&(this.scrollNodeIntoVisibleArea(g),this.focusNode(g));break;case l.UP:n!==null&&(this.scrollNodeIntoVisibleArea(n),this.focusNode(n));break;case l.DOWN:d!==null&&(this.scrollNodeIntoVisibleArea(d),this.focusNode(d));break;case l.LEFT:s.__expanded?s.hasChildren&&this.hideChildren(s):i&&(this.scrollNodeIntoVisibleArea(i),this.focusNode(i));break;case l.RIGHT:s.__expanded&&d?(this.scrollNodeIntoVisibleArea(d),this.focusNode(d)):s.hasChildren&&this.showChildren(s);break;case l.ENTER:case l.SPACE:this.selectNode(s);break;default:}}scrollNodeIntoVisibleArea(e){const t=e.__y,r=e.__y+this.nodeHeight,s=t>=this.currentScrollPosition,i=r<=this.currentScrollPosition+this.currentVisibleHeight;if(!(s&&i)){let n=this.currentScrollPosition;!s&&!i?n=r-this.currentVisibleHeight:s?i||(n=r-this.currentVisibleHeight):n=t,n<0&&(n=0),this.root.scrollTo({top:n})}}registerUnloadHandler(){try{if(!window.frameElement)return;window.addEventListener("pagehide",()=>this.muteErrorNotifications=!0,{once:!0})}catch{console.error("Failed to check the existence of window.frameElement \u2013 using a foreign origin?")}}}f([C({type:Object})],c.prototype,"setup",void 0),f([p()],c.prototype,"settings",void 0),f([$(".nodes-root")],c.prototype,"root",void 0),f([p()],c.prototype,"nodeMap",void 0),f([p()],c.prototype,"currentScrollPosition",void 0),f([p()],c.prototype,"currentVisibleHeight",void 0),f([p()],c.prototype,"searchTerm",void 0),f([p()],c.prototype,"searchResults",void 0),f([p()],c.prototype,"loading",void 0),f([p()],c.prototype,"hoveredNode",void 0),f([p()],c.prototype,"nodeDragAllowed",void 0);export{c as Tree,T as TreeFilterAppliedEvent,v as TreeFilterResetEvent,y as TreeNodeMap};
|