@vectoriox/iox-builder 9.5.3 → 9.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -7417,11 +7417,11 @@ class LayerTreeComponent {
|
|
|
7417
7417
|
return instance instanceof BuilderRepeaterComponent ? { alias: instance.source, count: instance.items.length } : null;
|
|
7418
7418
|
}
|
|
7419
7419
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: LayerTreeComponent, deps: [{ token: ComponentRegistryService }, { token: OverlayService }, { token: DragEngineService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7420
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: LayerTreeComponent, isStandalone: false, selector: "app-layer-tree", inputs: { layout: "layout", globalElements: "globalElements" }, outputs: { nodeSelect: "nodeSelect", nodeAction: "nodeAction", nodeMove: "nodeMove" }, ngImport: i0, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> {{ words.page }}\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> {{ words.global }}\n @if (flatGlobalTree.length) {\n <span class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n }\n </button>\n </div>\n\n <!-- A node's label with what the shipped Repeater adds to it (boards 4 / 8): its sub-label, the\n template chip, a composite part's role and lock, the hidden-at-rest glyph. -->\n <ng-template #rowLabel let-tn>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\" [attr.title]=\"rowTitle(tn)\">{{ tn.label }}@if (tn.sub) {<em class=\"node-sub\"> \u00B7 {{ tn.sub }}</em>}</span>\n @if (tn.template) {\n <span class=\"node-template\" [title]=\"templateTitle\">{{ templateLabel }}</span>\n }\n @if (tn.node.role) {\n <span class=\"node-role\" [title]=\"roleTitle + ': ' + tn.node.role\">{{ tn.node.role }}</span>\n }\n @if (tn.locked) {\n <i class=\"ph-thin ph-lock-simple node-lock\" [title]=\"lockedPartTitle\" [attr.aria-label]=\"lockedPartTitle\"></i>\n }\n @if (tn.hiddenAtRest) {\n <span class=\"node-rest\" [title]=\"hiddenAtRestTitle\" [attr.aria-label]=\"hiddenAtRestTitle\"><i class=\"ph-thin ph-eye-slash\"></i></span>\n }\n </ng-template>\n\n <!-- The rows a Repeater's source adds are not nodes: ONE muted line after its template, never selectable. -->\n <ng-template #moreRowsLine let-tn let-handle=\"handle\">\n <div class=\"tree-more\" aria-disabled=\"true\" [title]=\"moreRowsTitle\"\n [style.padding-inline-start.px]=\"12 + tn.moreRows.depth * 16\">\n @if (handle) {\n <i class=\"ph-thin ph-dots-six-vertical drag-handle tree-more-handle\" aria-hidden=\"true\"></i>\n }\n <span class=\"expand-spacer\"></span>\n <i class=\"ph-thin ph-rows node-icon\"></i>\n <span class=\"node-label\">{{ moreRowsText(tn.moreRows) }}</span>\n </div>\n </ng-template>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'page') {\n <div class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n @if (!flatTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>{{ words.empty }}</span>\n </div>\n }\n\n @for (tn of flatTree; track tn.node) {\n <div class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n @if (editingNodeId === tn.node.id) {\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" [title]=\"words.rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" [title]=\"words.duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n @if (!tn.locked) {\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n }\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn, handle: true }\"></ng-container>\n }\n }\n </div>\n }\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'global') {\n <div class=\"tree-body\">\n @if (!flatGlobalTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>{{ words.globalEmpty }}</span>\n </div>\n }\n\n @for (tn of flatGlobalTree; track tn.node) {\n <div class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n @if (tn.depth === 0) {\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn }\"></ng-container>\n }\n }\n </div>\n }\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;min-width:4.5em}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-sub{font-style:normal;font-weight:400;color:#535d6e}.layer-tree .node-template{flex:none;padding:0 4px;border-radius:4px;background:#8a3a72;color:#fff;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .tree-more{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;font-size:12px;font-style:italic;color:#64748b;border-inline-start:2px solid transparent;cursor:default;-webkit-user-select:none;user-select:none}.layer-tree .tree-more-handle{visibility:hidden}.layer-tree .node-role{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 4px;border:1px dashed #c9a1be;border-radius:4px;background:#f7eef5;color:#8a3a72;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .node-lock{flex:none;color:#64748b;font-size:12px}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:flex;gap:2px;margin-inline-start:auto;opacity:0;transition:opacity .12s;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions{opacity:1}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-rest{display:inline-flex;align-items:center;flex-shrink:0;font-size:12px;color:var(--p-text-muted-color)}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i5.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] }); }
|
|
7420
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.31", type: LayerTreeComponent, isStandalone: false, selector: "app-layer-tree", inputs: { layout: "layout", globalElements: "globalElements" }, outputs: { nodeSelect: "nodeSelect", nodeAction: "nodeAction", nodeMove: "nodeMove" }, ngImport: i0, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> {{ words.page }}\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> {{ words.global }}\n @if (flatGlobalTree.length) {\n <span class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n }\n </button>\n </div>\n\n <!-- A node's label with what the shipped Repeater adds to it (boards 4 / 8): its sub-label, the\n template chip, a composite part's role and lock, the hidden-at-rest glyph. -->\n <ng-template #rowLabel let-tn>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\" [attr.title]=\"rowTitle(tn)\">{{ tn.label }}@if (tn.sub) {<em class=\"node-sub\"> \u00B7 {{ tn.sub }}</em>}</span>\n @if (tn.template) {\n <span class=\"node-template\" [title]=\"templateTitle\">{{ templateLabel }}</span>\n }\n @if (tn.node.role) {\n <span class=\"node-role\" [title]=\"roleTitle + ': ' + tn.node.role\">{{ tn.node.role }}</span>\n }\n @if (tn.locked) {\n <i class=\"ph-thin ph-lock-simple node-lock\" [title]=\"lockedPartTitle\" [attr.aria-label]=\"lockedPartTitle\"></i>\n }\n @if (tn.hiddenAtRest) {\n <span class=\"node-rest\" [title]=\"hiddenAtRestTitle\" [attr.aria-label]=\"hiddenAtRestTitle\"><i class=\"ph-thin ph-eye-slash\"></i></span>\n }\n </ng-template>\n\n <!-- The rows a Repeater's source adds are not nodes: ONE muted line after its template, never selectable. -->\n <ng-template #moreRowsLine let-tn let-handle=\"handle\">\n <div class=\"tree-more\" aria-disabled=\"true\" [title]=\"moreRowsTitle\"\n [style.padding-inline-start.px]=\"12 + tn.moreRows.depth * 16\">\n @if (handle) {\n <i class=\"ph-thin ph-dots-six-vertical drag-handle tree-more-handle\" aria-hidden=\"true\"></i>\n }\n <span class=\"expand-spacer\"></span>\n <i class=\"ph-thin ph-rows node-icon\"></i>\n <span class=\"node-label\">{{ moreRowsText(tn.moreRows) }}</span>\n </div>\n </ng-template>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'page') {\n <div class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n @if (!flatTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>{{ words.empty }}</span>\n </div>\n }\n\n @for (tn of flatTree; track tn.node) {\n <div class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n @if (editingNodeId === tn.node.id) {\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" [title]=\"words.rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" [title]=\"words.duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n @if (!tn.locked) {\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n }\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn, handle: true }\"></ng-container>\n }\n }\n </div>\n }\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'global') {\n <div class=\"tree-body\">\n @if (!flatGlobalTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>{{ words.globalEmpty }}</span>\n </div>\n }\n\n @for (tn of flatGlobalTree; track tn.node) {\n <div class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n @if (tn.depth === 0) {\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn }\"></ng-container>\n }\n }\n </div>\n }\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;min-width:3em}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-sub{font-style:normal;font-weight:400;color:#535d6e}.layer-tree .node-template{flex:none;padding:0 4px;border-radius:4px;background:#8a3a72;color:#fff;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .tree-more{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;font-size:12px;font-style:italic;color:#64748b;border-inline-start:2px solid transparent;cursor:default;-webkit-user-select:none;user-select:none}.layer-tree .tree-more-handle{visibility:hidden}.layer-tree .node-role{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 4px;border:1px dashed #c9a1be;border-radius:4px;background:#f7eef5;color:#8a3a72;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .node-lock{flex:none;color:#64748b;font-size:12px}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:none;gap:2px;margin-inline-start:auto;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions,.layer-tree .tree-row:focus-within .node-actions{display:flex}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-rest{display:inline-flex;align-items:center;flex-shrink:0;font-size:12px;color:var(--p-text-muted-color)}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i5.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] }); }
|
|
7421
7421
|
}
|
|
7422
7422
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: LayerTreeComponent, decorators: [{
|
|
7423
7423
|
type: Component,
|
|
7424
|
-
args: [{ selector: 'app-layer-tree', standalone: false, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> {{ words.page }}\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> {{ words.global }}\n @if (flatGlobalTree.length) {\n <span class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n }\n </button>\n </div>\n\n <!-- A node's label with what the shipped Repeater adds to it (boards 4 / 8): its sub-label, the\n template chip, a composite part's role and lock, the hidden-at-rest glyph. -->\n <ng-template #rowLabel let-tn>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\" [attr.title]=\"rowTitle(tn)\">{{ tn.label }}@if (tn.sub) {<em class=\"node-sub\"> \u00B7 {{ tn.sub }}</em>}</span>\n @if (tn.template) {\n <span class=\"node-template\" [title]=\"templateTitle\">{{ templateLabel }}</span>\n }\n @if (tn.node.role) {\n <span class=\"node-role\" [title]=\"roleTitle + ': ' + tn.node.role\">{{ tn.node.role }}</span>\n }\n @if (tn.locked) {\n <i class=\"ph-thin ph-lock-simple node-lock\" [title]=\"lockedPartTitle\" [attr.aria-label]=\"lockedPartTitle\"></i>\n }\n @if (tn.hiddenAtRest) {\n <span class=\"node-rest\" [title]=\"hiddenAtRestTitle\" [attr.aria-label]=\"hiddenAtRestTitle\"><i class=\"ph-thin ph-eye-slash\"></i></span>\n }\n </ng-template>\n\n <!-- The rows a Repeater's source adds are not nodes: ONE muted line after its template, never selectable. -->\n <ng-template #moreRowsLine let-tn let-handle=\"handle\">\n <div class=\"tree-more\" aria-disabled=\"true\" [title]=\"moreRowsTitle\"\n [style.padding-inline-start.px]=\"12 + tn.moreRows.depth * 16\">\n @if (handle) {\n <i class=\"ph-thin ph-dots-six-vertical drag-handle tree-more-handle\" aria-hidden=\"true\"></i>\n }\n <span class=\"expand-spacer\"></span>\n <i class=\"ph-thin ph-rows node-icon\"></i>\n <span class=\"node-label\">{{ moreRowsText(tn.moreRows) }}</span>\n </div>\n </ng-template>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'page') {\n <div class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n @if (!flatTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>{{ words.empty }}</span>\n </div>\n }\n\n @for (tn of flatTree; track tn.node) {\n <div class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n @if (editingNodeId === tn.node.id) {\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" [title]=\"words.rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" [title]=\"words.duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n @if (!tn.locked) {\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n }\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn, handle: true }\"></ng-container>\n }\n }\n </div>\n }\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'global') {\n <div class=\"tree-body\">\n @if (!flatGlobalTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>{{ words.globalEmpty }}</span>\n </div>\n }\n\n @for (tn of flatGlobalTree; track tn.node) {\n <div class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n @if (tn.depth === 0) {\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn }\"></ng-container>\n }\n }\n </div>\n }\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;min-width:4.5em}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-sub{font-style:normal;font-weight:400;color:#535d6e}.layer-tree .node-template{flex:none;padding:0 4px;border-radius:4px;background:#8a3a72;color:#fff;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .tree-more{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;font-size:12px;font-style:italic;color:#64748b;border-inline-start:2px solid transparent;cursor:default;-webkit-user-select:none;user-select:none}.layer-tree .tree-more-handle{visibility:hidden}.layer-tree .node-role{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 4px;border:1px dashed #c9a1be;border-radius:4px;background:#f7eef5;color:#8a3a72;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .node-lock{flex:none;color:#64748b;font-size:12px}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:flex;gap:2px;margin-inline-start:auto;opacity:0;transition:opacity .12s;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions{opacity:1}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-rest{display:inline-flex;align-items:center;flex-shrink:0;font-size:12px;color:var(--p-text-muted-color)}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\n"] }]
|
|
7424
|
+
args: [{ selector: 'app-layer-tree', standalone: false, template: "<div class=\"layer-tree\">\n <div class=\"tree-header\">\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'page'\" (click)=\"activeSection = 'page'\">\n <i class=\"ph-thin ph-stack\"></i> {{ words.page }}\n </button>\n <button class=\"section-tab\" [class.section-tab--active]=\"activeSection === 'global'\" (click)=\"activeSection = 'global'\">\n <i class=\"ph-thin ph-globe\"></i> {{ words.global }}\n @if (flatGlobalTree.length) {\n <span class=\"section-tab-badge\">{{ flatGlobalTree.length }}</span>\n }\n </button>\n </div>\n\n <!-- A node's label with what the shipped Repeater adds to it (boards 4 / 8): its sub-label, the\n template chip, a composite part's role and lock, the hidden-at-rest glyph. -->\n <ng-template #rowLabel let-tn>\n <span class=\"node-label\" [class.node-label--named]=\"tn.node.label\" [attr.title]=\"rowTitle(tn)\">{{ tn.label }}@if (tn.sub) {<em class=\"node-sub\"> \u00B7 {{ tn.sub }}</em>}</span>\n @if (tn.template) {\n <span class=\"node-template\" [title]=\"templateTitle\">{{ templateLabel }}</span>\n }\n @if (tn.node.role) {\n <span class=\"node-role\" [title]=\"roleTitle + ': ' + tn.node.role\">{{ tn.node.role }}</span>\n }\n @if (tn.locked) {\n <i class=\"ph-thin ph-lock-simple node-lock\" [title]=\"lockedPartTitle\" [attr.aria-label]=\"lockedPartTitle\"></i>\n }\n @if (tn.hiddenAtRest) {\n <span class=\"node-rest\" [title]=\"hiddenAtRestTitle\" [attr.aria-label]=\"hiddenAtRestTitle\"><i class=\"ph-thin ph-eye-slash\"></i></span>\n }\n </ng-template>\n\n <!-- The rows a Repeater's source adds are not nodes: ONE muted line after its template, never selectable. -->\n <ng-template #moreRowsLine let-tn let-handle=\"handle\">\n <div class=\"tree-more\" aria-disabled=\"true\" [title]=\"moreRowsTitle\"\n [style.padding-inline-start.px]=\"12 + tn.moreRows.depth * 16\">\n @if (handle) {\n <i class=\"ph-thin ph-dots-six-vertical drag-handle tree-more-handle\" aria-hidden=\"true\"></i>\n }\n <span class=\"expand-spacer\"></span>\n <i class=\"ph-thin ph-rows node-icon\"></i>\n <span class=\"node-label\">{{ moreRowsText(tn.moreRows) }}</span>\n </div>\n </ng-template>\n\n <!-- \u2500\u2500 Page elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'page') {\n <div class=\"tree-body\"\n cdkDropList\n [cdkDropListData]=\"flatTree\"\n (cdkDropListDropped)=\"onTreeDrop($event)\">\n @if (!flatTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-tree-structure\"></i>\n <span>{{ words.empty }}</span>\n </div>\n }\n\n @for (tn of flatTree; track tn.node) {\n <div class=\"tree-row\"\n cdkDrag\n [cdkDragData]=\"tn\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n <i class=\"ph-thin ph-dots-six-vertical drag-handle\" cdkDragHandle></i>\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n @if (editingNodeId === tn.node.id) {\n <input class=\"node-rename-input\"\n [value]=\"editingValue\"\n (input)=\"editingValue = $any($event.target).value\"\n (keydown.enter)=\"saveRename(tn)\"\n (keydown.escape)=\"cancelRename()\"\n (blur)=\"saveRename(tn)\"\n (click)=\"$event.stopPropagation()\"\n autofocus>\n } @else {\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn\" [title]=\"words.rename\" (click)=\"startRename(tn, $event)\">\n <i class=\"ph-thin ph-pencil-simple\"></i>\n </button>\n <button class=\"action-btn\" [title]=\"words.duplicate\" (click)=\"onDuplicateNode(tn, $event)\">\n <i class=\"ph-thin ph-copy\"></i>\n </button>\n @if (!tn.locked) {\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n }\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn, handle: true }\"></ng-container>\n }\n }\n </div>\n }\n\n <!-- \u2500\u2500 Global elements tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (activeSection === 'global') {\n <div class=\"tree-body\">\n @if (!flatGlobalTree.length) {\n <div class=\"tree-empty\">\n <i class=\"ph-thin ph-globe\"></i>\n <span>{{ words.globalEmpty }}</span>\n </div>\n }\n\n @for (tn of flatGlobalTree; track tn.node) {\n <div class=\"tree-row tree-row--global\"\n [class.is-selected]=\"tn.node.id === selectedNodeId\"\n [class.is-hovered]=\"tn.node.id === hoveredNodeId\"\n [style.padding-inline-start.px]=\"12 + tn.depth * 16\"\n (click)=\"onNodeClick(tn)\"\n (mouseenter)=\"onNodeMouseEnter(tn)\"\n (mouseleave)=\"onNodeMouseLeave()\">\n\n @if (tn.hasChildren) {\n <button class=\"expand-btn\" (click)=\"toggleExpand(tn, $event)\">\n <i class=\"ph-thin\" [ngClass]=\"tn.expanded ? 'ph-caret-down' : 'ph-caret-right'\"></i>\n </button>\n } @else {\n <span class=\"expand-spacer\"></span>\n }\n\n <i [class]=\"tn.icon\" class=\"node-icon\"></i>\n <ng-container *ngTemplateOutlet=\"rowLabel; context: { $implicit: tn }\"></ng-container>\n @if (tn.depth === 0) {\n <span class=\"node-position-badge\">{{ tn.node.globalPosition }}</span>\n }\n\n <span class=\"node-actions\">\n <button class=\"action-btn action-btn--delete\" [title]=\"words.delete\" (click)=\"onDeleteNode(tn, $event)\">\n <i class=\"ph-thin ph-trash\"></i>\n </button>\n </span>\n </div>\n @if (tn.moreRows) {\n <ng-container *ngTemplateOutlet=\"moreRowsLine; context: { $implicit: tn }\"></ng-container>\n }\n }\n </div>\n }\n</div>\n", styles: [".layer-tree{display:flex;flex-direction:column;height:100%;overflow:hidden}.layer-tree .tree-header{display:flex;gap:2px;padding:6px 8px;border-bottom:1px solid var(--p-surface-200);flex-shrink:0}.layer-tree .section-tab{display:inline-flex;align-items:center;gap:4px;flex:1;justify-content:center;padding:4px 8px;font-size:11px;font-weight:500;border:1px solid var(--p-surface-200);border-radius:4px;background:transparent;color:var(--p-text-muted-color);cursor:pointer;transition:background .12s,color .12s,border-color .12s;white-space:nowrap}.layer-tree .section-tab i{font-size:11px}.layer-tree .section-tab:hover{background:var(--p-surface-100);color:var(--p-text-color)}.layer-tree .section-tab--active{background:#cb909026;border-color:#cb9090;color:#cb9090}.layer-tree .section-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;background:#cb9090;color:#fff;border-radius:8px}.layer-tree .tree-body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding-block:4px}.layer-tree .tree-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:2rem 1rem;color:var(--p-text-muted-color);font-size:12px}.layer-tree .tree-empty i{font-size:22px}.layer-tree .tree-row{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;cursor:pointer;font-size:12px;color:var(--p-text-color);border-inline-start:2px solid transparent;transition:background .12s,border-color .12s;-webkit-user-select:none;user-select:none}.layer-tree .tree-row:hover,.layer-tree .tree-row.is-hovered{background:var(--p-surface-100)}.layer-tree .tree-row.is-selected{background:#cb90901a;border-inline-start-color:#cb9090;font-weight:500}.layer-tree .drag-handle{font-size:10px;color:var(--p-text-muted-color);opacity:0;cursor:grab;flex-shrink:0;transition:opacity .12s}.layer-tree .tree-row:hover .drag-handle{opacity:.5}.layer-tree .drag-handle:hover{opacity:1!important}.layer-tree .cdk-drag-preview{box-sizing:border-box;display:flex;align-items:center;gap:6px;height:28px;padding:0 8px 0 12px;border-radius:6px;background:var(--p-surface-0);border:1px solid #cb9090;box-shadow:0 4px 12px #0000001f;font-size:12px}.layer-tree .cdk-drag-placeholder{height:2px;background:#cb9090;border-radius:1px;opacity:.6}.layer-tree .cdk-drag-placeholder>*{visibility:hidden}.layer-tree .cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.layer-tree .expand-btn{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;flex-shrink:0;border-radius:2px}.layer-tree .expand-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .expand-btn i{font-size:10px}.layer-tree .expand-spacer{width:16px;flex-shrink:0}.layer-tree .node-icon{font-size:14px;color:var(--p-text-muted-color);flex-shrink:0}.layer-tree .node-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;min-width:3em}.layer-tree .node-label.node-label--named{color:var(--p-primary-color, #cb9090);font-weight:500}.layer-tree .node-sub{font-style:normal;font-weight:400;color:#535d6e}.layer-tree .node-template{flex:none;padding:0 4px;border-radius:4px;background:#8a3a72;color:#fff;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .tree-more{display:flex;align-items:center;gap:6px;height:28px;padding-inline-end:8px;font-size:12px;font-style:italic;color:#64748b;border-inline-start:2px solid transparent;cursor:default;-webkit-user-select:none;user-select:none}.layer-tree .tree-more-handle{visibility:hidden}.layer-tree .node-role{flex:0 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;padding:0 4px;border:1px dashed #c9a1be;border-radius:4px;background:#f7eef5;color:#8a3a72;font:500 10px Fira Code,Fira Mono,monospace;line-height:16px}.layer-tree .node-lock{flex:none;color:#64748b;font-size:12px}.layer-tree .node-rename-input{flex:1;min-width:0;border:1px solid var(--p-primary-color, #cb9090);border-radius:4px;background:var(--p-surface-0, #fff);color:var(--p-text-color);font-family:inherit;font-size:.72rem;padding:1px 4px;outline:none}.layer-tree .node-actions{display:none;gap:2px;margin-inline-start:auto;flex-shrink:0}.layer-tree .tree-row:hover .node-actions,.layer-tree .tree-row.is-selected .node-actions,.layer-tree .tree-row:focus-within .node-actions{display:flex}.layer-tree .tree-section-header{display:flex;align-items:center;gap:6px;padding:6px 12px 4px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--p-text-muted-color);border-top:1px solid var(--p-surface-200);margin-top:4px}.layer-tree .tree-section-header i{font-size:12px}.layer-tree .tree-body--global{flex:0 0 auto}.layer-tree .tree-row--global{border-inline-start-color:transparent}.layer-tree .tree-row--global.is-selected{background:#638fcb1a;border-inline-start-color:#638fcb}.layer-tree .node-rest{display:inline-flex;align-items:center;flex-shrink:0;font-size:12px;color:var(--p-text-muted-color)}.layer-tree .node-position-badge{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:#638fcb;background:#638fcb1f;padding:1px 5px;border-radius:3px;flex-shrink:0}.layer-tree .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;background:transparent;color:var(--p-text-muted-color);cursor:pointer;border-radius:4px;font-size:12px;transition:background .12s,color .12s}.layer-tree .action-btn:hover{background:var(--p-surface-200);color:var(--p-text-color)}.layer-tree .action-btn--delete:hover{background:#dc26261a;color:#dc2626}\n"] }]
|
|
7425
7425
|
}], ctorParameters: () => [{ type: ComponentRegistryService }, { type: OverlayService }, { type: DragEngineService }], propDecorators: { layout: [{
|
|
7426
7426
|
type: Input
|
|
7427
7427
|
}], globalElements: [{
|