From d121833c2aeab58339a97c46c140c492e7071183 Mon Sep 17 00:00:00 2001 From: pk Date: Mon, 15 Dec 2025 23:12:34 +0100 Subject: [PATCH] wip --- tp-tree-nav.js | 136 ++++++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 65 deletions(-) diff --git a/tp-tree-nav.js b/tp-tree-nav.js index 2b54a9e..84809d3 100644 --- a/tp-tree-nav.js +++ b/tp-tree-nav.js @@ -7,7 +7,7 @@ This program is available under Apache License Version 2.0 import { LitElement, html, css, svg } from 'lit'; import { virtualize } from '@lit-labs/virtualizer/virtualize.js'; -class TpTreeNav extends LitElement { +export class TpTreeNav extends LitElement { static get styles() { return [ css` @@ -31,6 +31,8 @@ class TpTreeNav extends LitElement { padding: 0 8px; cursor: default; user-select: none; + gap: 5px; + width: 100%; } .row:hover { @@ -66,7 +68,6 @@ class TpTreeNav extends LitElement { } .icon { - margin-right: 6px; width: 18px; height: 18px; flex: 0 0 auto; @@ -140,6 +141,66 @@ class TpTreeNav extends LitElement { `; } + _renderItem(item) { + const { node, depth, hasChildren, expanded } = item; + const icon = this._resolveIcon(node?.icon); + + const custom = this.renderNode?.(item, { + depth, + states: Array.isArray(node?.states) ? node.states : [], + path: item.path, + hasChildren, + }); + + if (custom) { + return custom; + } + + return html` +
this._onRowClick(item, e)} + @contextmenu=${(e) => this._onContextMenu(item, e)} + > +
+
this._onChevronClick(item, e)} + > + +
+ ${icon ? html`` : html``} +
${node?.label ?? ''}
+
+ `; + } + + _renderContextMenu() { + if (!this._contextMenu) return null; + const { x, y, item, actions } = this._contextMenu; + + return html` +
+
+ ${actions.map((action) => html` + + `)} +
+
+ `; + } + static get properties() { return { roots: { type: Array }, @@ -217,44 +278,6 @@ class TpTreeNav extends LitElement { return results; } - _renderItem(item) { - const { node, depth, hasChildren, expanded } = item; - const icon = this._resolveIcon(node?.icon); - - const custom = this.renderNode?.(node, { - depth, - states: Array.isArray(node?.states) ? node.states : [], - path: item.path, - hasChildren, - }); - - if (custom) { - return custom; - } - - return html` -
this._onRowClick(item, e)} - @contextmenu=${(e) => this._onContextMenu(item, e)} - > -
-
this._onChevronClick(item, e)} - > - -
- ${icon ? html`` : html``} -
${node?.label ?? ''}
-
- `; - } - _onRowClick(item, originalEvent) { const ev = new CustomEvent('node-click', { detail: { node: item.node, path: item.path, originalEvent }, @@ -272,8 +295,9 @@ class TpTreeNav extends LitElement { async _onContextMenu(item, originalEvent) { originalEvent.preventDefault(); + const contextEvent = new CustomEvent('node-context', { - detail: { node: item.node, path: item.path, originalEvent }, + detail: { item, originalEvent }, bubbles: true, composed: true, cancelable: true, @@ -288,7 +312,7 @@ class TpTreeNav extends LitElement { ); const maybeModified = this.beforeContextMenu - ? this.beforeContextMenu(item.node, baseActions) + ? this.beforeContextMenu(item, baseActions) : baseActions; const actions = await Promise.resolve(maybeModified); @@ -305,7 +329,7 @@ class TpTreeNav extends LitElement { _dispatchAction(action, item, source, originalEvent) { const ev = new CustomEvent('node-action', { - detail: { action, node: item.node, path: item.path, source, originalEvent }, + detail: { action, item, source, originalEvent }, bubbles: true, composed: true, cancelable: true, @@ -313,28 +337,6 @@ class TpTreeNav extends LitElement { this.dispatchEvent(ev); } - _renderContextMenu() { - if (!this._contextMenu) return null; - const { x, y, item, actions } = this._contextMenu; - - return html` -
-
- ${actions.map((action) => html` - - `)} -
-
- `; - } - _onMenuAction(action, item, originalEvent) { originalEvent.stopPropagation(); this._dispatchAction(action?.action, item, 'context-menu', originalEvent); @@ -456,17 +458,21 @@ class TpTreeNav extends LitElement { const slug = node?.slug ?? `${index}`; const nextPath = [...path, slug]; const mappedNode = mapper(node, nextPath) ?? node; + const { nodes: childNodes, changed: childChanged } = this._mapTree( node?.children, mapper, nextPath ); + const children = childChanged ? childNodes : node?.children; const nodeChanged = mappedNode !== node || childChanged; + if (nodeChanged) { changed = true; return { ...mappedNode, children }; } + return mappedNode; }); return { nodes: mapped, changed };