phoenix-ui-components 4.2.0 → 4.2.3
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.
|
@@ -18,7 +18,7 @@ import * as i1$1 from '@angular/material/dialog';
|
|
|
18
18
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
19
19
|
import * as i2$2 from '@angular/material/icon';
|
|
20
20
|
import { MatIconModule } from '@angular/material/icon';
|
|
21
|
-
import { ActiveVariable, EventDisplay, SceneManager, PrettySymbols, Edm4hepJsonLoader, JiveXMLLoader, PHYSLITELoader, ATLASESDLoader, CMSLoader, readZipFile, VRManager, XRSessionType, ARManager, phoenixURLOptions, getAvailableColumns, DEFAULT_ETA_PHI_CONFIG, ATLAS_KINEMATICS, ATLAS_MASTERCLASS_CONFIG, invariantMass, fourMomentumFromCluster, fourMomentumFromTrack } from 'phoenix-event-display';
|
|
21
|
+
import { ActiveVariable, EventDisplay, SceneManager, PrettySymbols, Edm4hepJsonLoader, JiveXMLLoader, PHYSLITELoader, ATLASESDLoader, CMSLoader, readZipFile, VRManager, XRSessionType, ARManager, phoenixURLOptions, getAvailableColumns, DEFAULT_ETA_PHI_CONFIG, ATLAS_KINEMATICS, ATLAS_MASS_HISTOGRAM, ATLAS_MASTERCLASS_CONFIG, invariantMass, fourMomentumFromCluster, fourMomentumFromTrack } from 'phoenix-event-display';
|
|
22
22
|
import * as i2$3 from '@angular/material/snack-bar';
|
|
23
23
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
24
24
|
import RecordRTC from 'recordrtc';
|
|
@@ -29,7 +29,6 @@ import * as i3$1 from '@angular/material/tooltip';
|
|
|
29
29
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
30
30
|
import * as i4$2 from '@angular/material/menu';
|
|
31
31
|
import { MatMenuTrigger, MatMenuModule } from '@angular/material/menu';
|
|
32
|
-
import { ResizeSensor } from 'css-element-queries';
|
|
33
32
|
import * as i3$2 from '@angular/cdk/drag-drop';
|
|
34
33
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
35
34
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
@@ -46,6 +45,8 @@ import { MatTreeNestedDataSource } from '@angular/material/tree';
|
|
|
46
45
|
import JSZip from 'jszip';
|
|
47
46
|
import * as i6 from '@angular/material/tabs';
|
|
48
47
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
48
|
+
import { createHistogram, gStyle } from 'jsroot';
|
|
49
|
+
import { draw, redraw } from 'jsroot/draw';
|
|
49
50
|
|
|
50
51
|
class NavComponent {
|
|
51
52
|
constructor() { }
|
|
@@ -141,7 +142,7 @@ class ConfigSliderComponent {
|
|
|
141
142
|
}] }); })();
|
|
142
143
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConfigSliderComponent, { className: "ConfigSliderComponent", filePath: "components/phoenix-menu/config/config-slider/config-slider.component.ts", lineNumber: 11 }); })();
|
|
143
144
|
|
|
144
|
-
const _c0$
|
|
145
|
+
const _c0$f = ["phoenixMenuItem"];
|
|
145
146
|
const _c1$7 = a0 => ({ expanded: a0 });
|
|
146
147
|
const _c2$3 = a0 => ({ "top.px": a0 });
|
|
147
148
|
const _c3$2 = a0 => ({ "range-slider-row": a0 });
|
|
@@ -517,7 +518,7 @@ class PhoenixMenuItemComponent {
|
|
|
517
518
|
}
|
|
518
519
|
static ɵfac = function PhoenixMenuItemComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PhoenixMenuItemComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
|
|
519
520
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PhoenixMenuItemComponent, selectors: [["app-phoenix-menu-item"]], viewQuery: function PhoenixMenuItemComponent_Query(rf, ctx) { if (rf & 1) {
|
|
520
|
-
i0.ɵɵviewQuery(_c0$
|
|
521
|
+
i0.ɵɵviewQuery(_c0$f, 5);
|
|
521
522
|
} if (rf & 2) {
|
|
522
523
|
let _t;
|
|
523
524
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.phoenixMenuItem = _t.first);
|
|
@@ -528,11 +529,11 @@ class PhoenixMenuItemComponent {
|
|
|
528
529
|
i0.ɵɵproperty("ngIf", ctx.isCompact)("ngIfElse", fullItem_r19);
|
|
529
530
|
i0.ɵɵadvance(3);
|
|
530
531
|
i0.ɵɵproperty("ngIf", ctx.currentNode.childrenActive);
|
|
531
|
-
} }, dependencies: [i2.NgClass, i2.NgForOf, i2.NgIf, i2.NgTemplateOutlet, i2.NgStyle, i2.NgSwitch, i2.NgSwitchCase, i3.MatButton, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.NumberValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.MatSlideToggle, i5.MatCheckbox, PhoenixMenuItemComponent, ConfigSliderComponent], styles: [".phoenix-menu-item{width:100%;padding:.6rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);font-size:.8rem;transition:all .5s;display:flex;justify-content:space-between;align-items:center}.phoenix-menu-item-left{display:flex;justify-content:flex-start;min-width:0;padding-right:.5rem;overflow:hidden}.phoenix-menu-item-left .item-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.phoenix-menu-item-left .item-icon{margin-right:.2rem}.phoenix-menu-item-right{display:flex;justify-content:flex-end}.phoenix-menu-item-right .item-expand.expanded{transform:scaleY(-1)}.phoenix-menu-item-right .item-settings{margin-right:.2rem}@media screen and (max-width:768px){.phoenix-menu-item{font-size:.75rem;padding:.5rem}}.phoenix-menu-item-compact{flex:1;min-width:0;color:var(--phoenix-text-color)}.phoenix-menu-item-compact .compact-option-button{width:100%;display:flex;flex-direction:column;align-items:center;gap:.15rem;padding:.3rem .2rem;color:inherit;border-radius:.3rem;transition:all .4s}.phoenix-menu-item-compact .compact-option-button:hover{background:var(--phoenix-options-icon-bg);cursor:pointer}.phoenix-menu-item-compact .compact-option-button .compact-option-label{font-size:.65rem;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.phoenix-menu-options-bar{display:flex;align-items:stretch;gap:.25rem;padding:.25rem .4rem;background:var(--phoenix-background-color-secondary)}.phoenix-menu-options-bar app-phoenix-menu-item{display:flex;flex:1;min-width:0}.phoenix-menu-item .item-config-backdrop,.phoenix-menu-item-compact .item-config-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:110}.phoenix-menu-item .item-config,.phoenix-menu-item-compact .item-config{position:absolute;right:100%;width:14rem;padding:.5rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color-secondary);box-shadow:var(--phoenix-box-shadow);display:flex;flex-direction:column;z-index:120;max-height:60vh;overflow-y:auto;font-size:.8rem}.phoenix-menu-item .item-config::-webkit-scrollbar,.phoenix-menu-item-compact .item-config::-webkit-scrollbar{width:4px}.phoenix-menu-item .item-config::-webkit-scrollbar-thumb,.phoenix-menu-item-compact .item-config::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}.phoenix-menu-item .item-config>*,.phoenix-menu-item-compact .item-config>*{margin-bottom:.4rem}.phoenix-menu-item .item-config>*:last-child,.phoenix-menu-item-compact .item-config>*:last-child{margin-bottom:0}.phoenix-menu-item .item-config .item-config-single,.phoenix-menu-item-compact .item-config .item-config-single{display:flex;flex-direction:row}.phoenix-menu-item .item-config .item-config-single .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single .item-config-label{width:30%}.phoenix-menu-item .item-config .item-config-single .item-config-data,.phoenix-menu-item-compact .item-config .item-config-single .item-config-data{flex-grow:1;padding-left:.5rem;min-width:0}.phoenix-menu-item .item-config .item-config-single.range-slider-row,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row{align-items:center}.phoenix-menu-item .item-config .item-config-single.range-slider-row .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row .item-config-label{width:auto;min-width:1.6rem;flex-shrink:0;margin-bottom:0}.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{display:inline-block;width:1.3rem;height:1.3rem;padding:.23rem;transition:all .4s}.phoenix-menu-item .icon-wrapper.icon-button:hover,.phoenix-menu-item-compact .icon-wrapper.icon-button:hover{background:var(--phoenix-options-icon-bg);border-radius:40%;cursor:pointer}.phoenix-menu-item .icon-wrapper svg,.phoenix-menu-item-compact .icon-wrapper svg{width:100%;height:100%;vertical-align:top}.phoenix-menu-item .mat-slide-toggle-bar,.phoenix-menu-item-compact .mat-slide-toggle-bar{width:30px!important}.phoenix-menu-item .mat-slide-toggle-thumb,.phoenix-menu-item-compact .mat-slide-toggle-thumb{width:15px!important;height:15px!important;position:absolute;top:2px}.phoenix-menu-item .mat-slider-horizontal,.phoenix-menu-item-compact .mat-slider-horizontal{min-width:0;width:100%;height:20px}.phoenix-menu-item .mat-slider-horizontal .mat-slider-wrapper,.phoenix-menu-item-compact .mat-slider-horizontal .mat-slider-wrapper{top:10px}.phoenix-menu-item label.mat-checkbox-layout,.phoenix-menu-item-compact label.mat-checkbox-layout{margin:0}@media screen and (max-width:768px){.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{width:1rem;height:1rem;padding:.15rem}}.phoenix-menu-children{margin-left:.5rem;border-left:1px solid var(--phoenix-accent)
|
|
532
|
+
} }, dependencies: [i2.NgClass, i2.NgForOf, i2.NgIf, i2.NgTemplateOutlet, i2.NgStyle, i2.NgSwitch, i2.NgSwitchCase, i3.MatButton, i4.NgSelectOption, i4.ɵNgSelectMultipleOption, i4.DefaultValueAccessor, i4.NumberValueAccessor, i4.NgControlStatus, i4.NgModel, i4$1.MatSlideToggle, i5.MatCheckbox, PhoenixMenuItemComponent, ConfigSliderComponent], styles: [".phoenix-menu-item{width:100%;padding:.6rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);font-size:.8rem;transition:all .5s;display:flex;justify-content:space-between;align-items:center}.phoenix-menu-item-left{display:flex;justify-content:flex-start;min-width:0;padding-right:.5rem;overflow:hidden}.phoenix-menu-item-left .item-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.phoenix-menu-item-left .item-icon{margin-right:.2rem}.phoenix-menu-item-right{display:flex;justify-content:flex-end}.phoenix-menu-item-right .item-expand.expanded{transform:scaleY(-1)}.phoenix-menu-item-right .item-settings{margin-right:.2rem}@media screen and (max-width:768px){.phoenix-menu-item{font-size:.75rem;padding:.5rem}}.phoenix-menu-item-compact{flex:1;min-width:0;color:var(--phoenix-text-color)}.phoenix-menu-item-compact .compact-option-button{width:100%;display:flex;flex-direction:column;align-items:center;gap:.15rem;padding:.3rem .2rem;color:inherit;border-radius:.3rem;transition:all .4s}.phoenix-menu-item-compact .compact-option-button:hover{background:var(--phoenix-options-icon-bg);cursor:pointer}.phoenix-menu-item-compact .compact-option-button .compact-option-label{font-size:.65rem;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.phoenix-menu-options-bar{display:flex;align-items:stretch;gap:.25rem;padding:.25rem .4rem;background:var(--phoenix-background-color-secondary)}.phoenix-menu-options-bar app-phoenix-menu-item{display:flex;flex:1;min-width:0}.phoenix-menu-item .item-config-backdrop,.phoenix-menu-item-compact .item-config-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:110}.phoenix-menu-item .item-config,.phoenix-menu-item-compact .item-config{position:absolute;right:100%;width:14rem;padding:.5rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color-secondary);box-shadow:var(--phoenix-box-shadow);display:flex;flex-direction:column;z-index:120;max-height:60vh;overflow-y:auto;font-size:.8rem}.phoenix-menu-item .item-config::-webkit-scrollbar,.phoenix-menu-item-compact .item-config::-webkit-scrollbar{width:4px}.phoenix-menu-item .item-config::-webkit-scrollbar-thumb,.phoenix-menu-item-compact .item-config::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}.phoenix-menu-item .item-config>*,.phoenix-menu-item-compact .item-config>*{margin-bottom:.4rem}.phoenix-menu-item .item-config>*:last-child,.phoenix-menu-item-compact .item-config>*:last-child{margin-bottom:0}.phoenix-menu-item .item-config .item-config-single,.phoenix-menu-item-compact .item-config .item-config-single{display:flex;flex-direction:row}.phoenix-menu-item .item-config .item-config-single .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single .item-config-label{width:30%}.phoenix-menu-item .item-config .item-config-single .item-config-data,.phoenix-menu-item-compact .item-config .item-config-single .item-config-data{flex-grow:1;padding-left:.5rem;min-width:0}.phoenix-menu-item .item-config .item-config-single.range-slider-row,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row{align-items:center}.phoenix-menu-item .item-config .item-config-single.range-slider-row .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row .item-config-label{width:auto;min-width:1.6rem;flex-shrink:0;margin-bottom:0}.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{display:inline-block;width:1.3rem;height:1.3rem;padding:.23rem;transition:all .4s}.phoenix-menu-item .icon-wrapper.icon-button:hover,.phoenix-menu-item-compact .icon-wrapper.icon-button:hover{background:var(--phoenix-options-icon-bg);border-radius:40%;cursor:pointer}.phoenix-menu-item .icon-wrapper svg,.phoenix-menu-item-compact .icon-wrapper svg{width:100%;height:100%;vertical-align:top}.phoenix-menu-item .mat-slide-toggle-bar,.phoenix-menu-item-compact .mat-slide-toggle-bar{width:30px!important}.phoenix-menu-item .mat-slide-toggle-thumb,.phoenix-menu-item-compact .mat-slide-toggle-thumb{width:15px!important;height:15px!important;position:absolute;top:2px}.phoenix-menu-item .mat-slider-horizontal,.phoenix-menu-item-compact .mat-slider-horizontal{min-width:0;width:100%;height:20px}.phoenix-menu-item .mat-slider-horizontal .mat-slider-wrapper,.phoenix-menu-item-compact .mat-slider-horizontal .mat-slider-wrapper{top:10px}.phoenix-menu-item label.mat-checkbox-layout,.phoenix-menu-item-compact label.mat-checkbox-layout{margin:0}@media screen and (max-width:768px){.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{width:1rem;height:1rem;padding:.15rem}}.phoenix-menu-children{margin-left:.5rem;border-left:1px solid var(--phoenix-accent)}.range-slider .range-slider-inputs{gap:4px}.range-slider .range-slider-side{display:flex;align-items:center;flex:1;gap:3px;min-width:0}.range-slider .range-slider-side mat-checkbox{flex-shrink:0;--mdc-checkbox-state-layer-size: 24px}.range-slider .range-slider-side input[type=number]{min-width:0;width:100%;padding:.15rem .25rem;font-size:.75rem;appearance:textfield;-moz-appearance:textfield}.range-slider .range-slider-side input[type=number]::-webkit-outer-spin-button,.range-slider .range-slider-side input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"], encapsulation: 2 });
|
|
532
533
|
}
|
|
533
534
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PhoenixMenuItemComponent, [{
|
|
534
535
|
type: Component,
|
|
535
|
-
args: [{ standalone: false, selector: 'app-phoenix-menu-item', encapsulation: ViewEncapsulation.None, template: "<!-- Leaf nodes holding only configs (Draw/Cut/Color Options) are shown as a\n compact icon button; everything else as a full menu row. -->\n<div\n *ngIf=\"isCompact; else fullItem\"\n class=\"phoenix-menu-item-compact\"\n #phoenixMenuItem\n>\n <button\n class=\"btn-blank compact-option-button\"\n [title]=\"currentNode.name\"\n (click)=\"\n calculateConfigTop(); currentNode.configActive = !currentNode.configActive\n \"\n >\n <span class=\"icon-wrapper\">\n <svg>\n <use\n attr.href=\"assets/icons/{{ currentNode.icon }}.svg#{{\n currentNode.icon\n }}\"\n ></use>\n </svg>\n </span>\n <span class=\"compact-option-label\">{{ compactLabel }}</span>\n </button>\n <ng-container *ngTemplateOutlet=\"configPopup\"></ng-container>\n</div>\n\n<ng-template #fullItem>\n <div class=\"phoenix-menu-item\" #phoenixMenuItem>\n <div class=\"phoenix-menu-item-left align-items-center\">\n <!-- If the item has some toggle function -->\n <ng-container *ngIf=\"currentNode.onToggle; else nodeName\">\n <mat-slide-toggle\n [checked]=\"currentNode.toggleState\"\n (change)=\"currentNode.toggleSelfAndDescendants($event.checked)\"\n >\n <ng-container *ngTemplateOutlet=\"nodeName\"></ng-container>\n </mat-slide-toggle>\n </ng-container>\n <!-- If the item has no toggle function -->\n <ng-template #nodeName>\n <span class=\"d-flex w-100 align-items-center\">\n <span *ngIf=\"currentNode.icon\" class=\"icon-wrapper item-icon\">\n <svg>\n <use\n attr.href=\"assets/icons/{{ currentNode.icon }}.svg#{{\n currentNode.icon\n }}\"\n ></use>\n </svg>\n </span>\n <span class=\"item-name\" [title]=\"currentNode.name\">{{\n currentNode.name\n }}</span>\n </span>\n </ng-template>\n </div>\n <div class=\"phoenix-menu-item-right\">\n <div *ngIf=\"currentNode.configs.length > 0\">\n <button\n class=\"icon-wrapper icon-button btn-blank item-settings\"\n (click)=\"\n calculateConfigTop();\n currentNode.configActive = !currentNode.configActive\n \"\n >\n <svg>\n <use href=\"assets/icons/gear.svg#gear\"></use>\n </svg>\n </button>\n <ng-container *ngTemplateOutlet=\"configPopup\"></ng-container>\n </div>\n <button\n class=\"icon-wrapper icon-button btn-blank item-expand\"\n *ngIf=\"currentNode.children.length > 0\"\n (click)=\"currentNode.childrenActive = !currentNode.childrenActive\"\n [ngClass]=\"{ expanded: currentNode.childrenActive }\"\n data-testid=\"dropdown\"\n >\n <svg>\n <use href=\"assets/icons/expand.svg#expand\"></use>\n </svg>\n </button>\n </div>\n </div>\n</ng-template>\n\n<div class=\"phoenix-menu-children\" *ngIf=\"currentNode.childrenActive\">\n <div class=\"phoenix-menu-options-bar\" *ngIf=\"compactChildren.length > 0\">\n <app-phoenix-menu-item\n *ngFor=\"let childNode of compactChildren\"\n [currentNode]=\"childNode\"\n >\n </app-phoenix-menu-item>\n </div>\n <app-phoenix-menu-item\n *ngFor=\"let childNode of regularChildren\"\n [currentNode]=\"childNode\"\n >\n </app-phoenix-menu-item>\n</div>\n\n<!-- Config popup shared by the full row (gear button) and the compact icon button -->\n<ng-template #configPopup>\n <div\n class=\"item-config-backdrop\"\n *ngIf=\"currentNode.configActive\"\n (click)=\"currentNode.configActive = false\"\n ></div>\n <div\n class=\"item-config\"\n [hidden]=\"!currentNode.configActive\"\n [ngStyle]=\"{ 'top.px': configTop }\"\n >\n <ng-container\n *ngFor=\"let config of castConfigsToAny(currentNode.configs)\"\n [ngSwitch]=\"config.type\"\n >\n <!-- Config types -->\n <div\n class=\"item-config-single\"\n [ngClass]=\"{ 'range-slider-row': config.type === 'rangeSlider' }\"\n *ngIf=\"!config.hidden\"\n >\n <label\n class=\"item-config-label\"\n for=\"item-config-field\"\n *ngIf=\"config.type !== 'button'\"\n [ngClass]=\"{ 'font-weight-bold w-100': config.type === 'label' }\"\n >\n {{ config.label }}\n </label>\n <div\n class=\"item-config-data\"\n [ngClass]=\"{ 'p-0': config.type === 'button' }\"\n *ngIf=\"config.type !== 'label'\"\n >\n <mat-checkbox\n *ngSwitchCase=\"'checkbox'\"\n [checked]=\"config.isChecked\"\n (change)=\"\n config.onChange($event.checked); config.isChecked = $event.checked\n \"\n ></mat-checkbox>\n\n <app-config-slider\n *ngSwitchCase=\"'slider'\"\n [value]=\"config.value\"\n (onChange)=\"config.onChange($event); config.value = $event\"\n [min]=\"config.min\"\n [max]=\"config.max\"\n [step]=\"config.step\"\n [allowCustomValue]=\"config.allowCustomValue\"\n >\n </app-config-slider>\n\n <button\n *ngSwitchCase=\"'button'\"\n class=\"w-100\"\n (click)=\"config.onClick()\"\n mat-button\n mat-stroked-button\n >\n {{ config.label }}\n </button>\n\n <input\n *ngSwitchCase=\"'color'\"\n id=\"item-config-field\"\n type=\"color\"\n [value]=\"config.color\"\n (input)=\"\n config.onChange($event.target.value);\n config.color = $event.target.value\n \"\n />\n\n <div *ngSwitchCase=\"'rangeSlider'\" class=\"range-slider\">\n <div class=\"range-slider-inputs d-flex align-items-center\">\n <div class=\"range-slider-side\">\n <mat-checkbox\n [(ngModel)]=\"config.enableMin\"\n (change)=\"config.setEnableMin($event.checked)\"\n ></mat-checkbox>\n <input\n type=\"number\"\n placeholder=\"Min\"\n class=\"form-control form-control-sm\"\n [(ngModel)]=\"config.value\"\n (input)=\"\n config.value = $event.target.value; config.onChange(config)\n \"\n [step]=\"config.step\"\n />\n </div>\n <div class=\"range-slider-side\">\n <mat-checkbox\n [(ngModel)]=\"config.enableMax\"\n (change)=\"config.setEnableMax($event.checked)\"\n ></mat-checkbox>\n <input\n type=\"number\"\n placeholder=\"Max\"\n class=\"form-control form-control-sm\"\n [(ngModel)]=\"config.highValue\"\n (input)=\"\n config.highValue = $event.target.value;\n config.onChange(config)\n \"\n [step]=\"config.step\"\n />\n </div>\n </div>\n </div>\n\n <select\n *ngSwitchCase=\"'select'\"\n id=\"item-config-field\"\n class=\"w-100\"\n [value]=\"config.value ?? config.options[0]\"\n (change)=\"config.onChange($event.target.value)\"\n >\n <option\n *ngFor=\"let singleOption of config.options\"\n [value]=\"singleOption\"\n >\n {{ singleOption }}\n </option>\n </select>\n </div>\n </div>\n <!-- Config types END -->\n </ng-container>\n </div>\n</ng-template>\n", styles: [".phoenix-menu-item{width:100%;padding:.6rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);font-size:.8rem;transition:all .5s;display:flex;justify-content:space-between;align-items:center}.phoenix-menu-item-left{display:flex;justify-content:flex-start;min-width:0;padding-right:.5rem;overflow:hidden}.phoenix-menu-item-left .item-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.phoenix-menu-item-left .item-icon{margin-right:.2rem}.phoenix-menu-item-right{display:flex;justify-content:flex-end}.phoenix-menu-item-right .item-expand.expanded{transform:scaleY(-1)}.phoenix-menu-item-right .item-settings{margin-right:.2rem}@media screen and (max-width:768px){.phoenix-menu-item{font-size:.75rem;padding:.5rem}}.phoenix-menu-item-compact{flex:1;min-width:0;color:var(--phoenix-text-color)}.phoenix-menu-item-compact .compact-option-button{width:100%;display:flex;flex-direction:column;align-items:center;gap:.15rem;padding:.3rem .2rem;color:inherit;border-radius:.3rem;transition:all .4s}.phoenix-menu-item-compact .compact-option-button:hover{background:var(--phoenix-options-icon-bg);cursor:pointer}.phoenix-menu-item-compact .compact-option-button .compact-option-label{font-size:.65rem;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.phoenix-menu-options-bar{display:flex;align-items:stretch;gap:.25rem;padding:.25rem .4rem;background:var(--phoenix-background-color-secondary)}.phoenix-menu-options-bar app-phoenix-menu-item{display:flex;flex:1;min-width:0}.phoenix-menu-item .item-config-backdrop,.phoenix-menu-item-compact .item-config-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:110}.phoenix-menu-item .item-config,.phoenix-menu-item-compact .item-config{position:absolute;right:100%;width:14rem;padding:.5rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color-secondary);box-shadow:var(--phoenix-box-shadow);display:flex;flex-direction:column;z-index:120;max-height:60vh;overflow-y:auto;font-size:.8rem}.phoenix-menu-item .item-config::-webkit-scrollbar,.phoenix-menu-item-compact .item-config::-webkit-scrollbar{width:4px}.phoenix-menu-item .item-config::-webkit-scrollbar-thumb,.phoenix-menu-item-compact .item-config::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}.phoenix-menu-item .item-config>*,.phoenix-menu-item-compact .item-config>*{margin-bottom:.4rem}.phoenix-menu-item .item-config>*:last-child,.phoenix-menu-item-compact .item-config>*:last-child{margin-bottom:0}.phoenix-menu-item .item-config .item-config-single,.phoenix-menu-item-compact .item-config .item-config-single{display:flex;flex-direction:row}.phoenix-menu-item .item-config .item-config-single .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single .item-config-label{width:30%}.phoenix-menu-item .item-config .item-config-single .item-config-data,.phoenix-menu-item-compact .item-config .item-config-single .item-config-data{flex-grow:1;padding-left:.5rem;min-width:0}.phoenix-menu-item .item-config .item-config-single.range-slider-row,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row{align-items:center}.phoenix-menu-item .item-config .item-config-single.range-slider-row .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row .item-config-label{width:auto;min-width:1.6rem;flex-shrink:0;margin-bottom:0}.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{display:inline-block;width:1.3rem;height:1.3rem;padding:.23rem;transition:all .4s}.phoenix-menu-item .icon-wrapper.icon-button:hover,.phoenix-menu-item-compact .icon-wrapper.icon-button:hover{background:var(--phoenix-options-icon-bg);border-radius:40%;cursor:pointer}.phoenix-menu-item .icon-wrapper svg,.phoenix-menu-item-compact .icon-wrapper svg{width:100%;height:100%;vertical-align:top}.phoenix-menu-item .mat-slide-toggle-bar,.phoenix-menu-item-compact .mat-slide-toggle-bar{width:30px!important}.phoenix-menu-item .mat-slide-toggle-thumb,.phoenix-menu-item-compact .mat-slide-toggle-thumb{width:15px!important;height:15px!important;position:absolute;top:2px}.phoenix-menu-item .mat-slider-horizontal,.phoenix-menu-item-compact .mat-slider-horizontal{min-width:0;width:100%;height:20px}.phoenix-menu-item .mat-slider-horizontal .mat-slider-wrapper,.phoenix-menu-item-compact .mat-slider-horizontal .mat-slider-wrapper{top:10px}.phoenix-menu-item label.mat-checkbox-layout,.phoenix-menu-item-compact label.mat-checkbox-layout{margin:0}@media screen and (max-width:768px){.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{width:1rem;height:1rem;padding:.15rem}}.phoenix-menu-children{margin-left:.5rem;border-left:1px solid var(--phoenix-accent);max-height:35vh;overflow-y:auto}.phoenix-menu-children::-webkit-scrollbar{width:4px}.phoenix-menu-children::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}.range-slider .range-slider-inputs{gap:4px}.range-slider .range-slider-side{display:flex;align-items:center;flex:1;gap:3px;min-width:0}.range-slider .range-slider-side mat-checkbox{flex-shrink:0;--mdc-checkbox-state-layer-size: 24px}.range-slider .range-slider-side input[type=number]{min-width:0;width:100%;padding:.15rem .25rem;font-size:.75rem;appearance:textfield;-moz-appearance:textfield}.range-slider .range-slider-side input[type=number]::-webkit-outer-spin-button,.range-slider .range-slider-side input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
|
|
536
|
+
args: [{ standalone: false, selector: 'app-phoenix-menu-item', encapsulation: ViewEncapsulation.None, template: "<!-- Leaf nodes holding only configs (Draw/Cut/Color Options) are shown as a\n compact icon button; everything else as a full menu row. -->\n<div\n *ngIf=\"isCompact; else fullItem\"\n class=\"phoenix-menu-item-compact\"\n #phoenixMenuItem\n>\n <button\n class=\"btn-blank compact-option-button\"\n [title]=\"currentNode.name\"\n (click)=\"\n calculateConfigTop(); currentNode.configActive = !currentNode.configActive\n \"\n >\n <span class=\"icon-wrapper\">\n <svg>\n <use\n attr.href=\"assets/icons/{{ currentNode.icon }}.svg#{{\n currentNode.icon\n }}\"\n ></use>\n </svg>\n </span>\n <span class=\"compact-option-label\">{{ compactLabel }}</span>\n </button>\n <ng-container *ngTemplateOutlet=\"configPopup\"></ng-container>\n</div>\n\n<ng-template #fullItem>\n <div class=\"phoenix-menu-item\" #phoenixMenuItem>\n <div class=\"phoenix-menu-item-left align-items-center\">\n <!-- If the item has some toggle function -->\n <ng-container *ngIf=\"currentNode.onToggle; else nodeName\">\n <mat-slide-toggle\n [checked]=\"currentNode.toggleState\"\n (change)=\"currentNode.toggleSelfAndDescendants($event.checked)\"\n >\n <ng-container *ngTemplateOutlet=\"nodeName\"></ng-container>\n </mat-slide-toggle>\n </ng-container>\n <!-- If the item has no toggle function -->\n <ng-template #nodeName>\n <span class=\"d-flex w-100 align-items-center\">\n <span *ngIf=\"currentNode.icon\" class=\"icon-wrapper item-icon\">\n <svg>\n <use\n attr.href=\"assets/icons/{{ currentNode.icon }}.svg#{{\n currentNode.icon\n }}\"\n ></use>\n </svg>\n </span>\n <span class=\"item-name\" [title]=\"currentNode.name\">{{\n currentNode.name\n }}</span>\n </span>\n </ng-template>\n </div>\n <div class=\"phoenix-menu-item-right\">\n <div *ngIf=\"currentNode.configs.length > 0\">\n <button\n class=\"icon-wrapper icon-button btn-blank item-settings\"\n (click)=\"\n calculateConfigTop();\n currentNode.configActive = !currentNode.configActive\n \"\n >\n <svg>\n <use href=\"assets/icons/gear.svg#gear\"></use>\n </svg>\n </button>\n <ng-container *ngTemplateOutlet=\"configPopup\"></ng-container>\n </div>\n <button\n class=\"icon-wrapper icon-button btn-blank item-expand\"\n *ngIf=\"currentNode.children.length > 0\"\n (click)=\"currentNode.childrenActive = !currentNode.childrenActive\"\n [ngClass]=\"{ expanded: currentNode.childrenActive }\"\n data-testid=\"dropdown\"\n >\n <svg>\n <use href=\"assets/icons/expand.svg#expand\"></use>\n </svg>\n </button>\n </div>\n </div>\n</ng-template>\n\n<div class=\"phoenix-menu-children\" *ngIf=\"currentNode.childrenActive\">\n <div class=\"phoenix-menu-options-bar\" *ngIf=\"compactChildren.length > 0\">\n <app-phoenix-menu-item\n *ngFor=\"let childNode of compactChildren\"\n [currentNode]=\"childNode\"\n >\n </app-phoenix-menu-item>\n </div>\n <app-phoenix-menu-item\n *ngFor=\"let childNode of regularChildren\"\n [currentNode]=\"childNode\"\n >\n </app-phoenix-menu-item>\n</div>\n\n<!-- Config popup shared by the full row (gear button) and the compact icon button -->\n<ng-template #configPopup>\n <div\n class=\"item-config-backdrop\"\n *ngIf=\"currentNode.configActive\"\n (click)=\"currentNode.configActive = false\"\n ></div>\n <div\n class=\"item-config\"\n [hidden]=\"!currentNode.configActive\"\n [ngStyle]=\"{ 'top.px': configTop }\"\n >\n <ng-container\n *ngFor=\"let config of castConfigsToAny(currentNode.configs)\"\n [ngSwitch]=\"config.type\"\n >\n <!-- Config types -->\n <div\n class=\"item-config-single\"\n [ngClass]=\"{ 'range-slider-row': config.type === 'rangeSlider' }\"\n *ngIf=\"!config.hidden\"\n >\n <label\n class=\"item-config-label\"\n for=\"item-config-field\"\n *ngIf=\"config.type !== 'button'\"\n [ngClass]=\"{ 'font-weight-bold w-100': config.type === 'label' }\"\n >\n {{ config.label }}\n </label>\n <div\n class=\"item-config-data\"\n [ngClass]=\"{ 'p-0': config.type === 'button' }\"\n *ngIf=\"config.type !== 'label'\"\n >\n <mat-checkbox\n *ngSwitchCase=\"'checkbox'\"\n [checked]=\"config.isChecked\"\n (change)=\"\n config.onChange($event.checked); config.isChecked = $event.checked\n \"\n ></mat-checkbox>\n\n <app-config-slider\n *ngSwitchCase=\"'slider'\"\n [value]=\"config.value\"\n (onChange)=\"config.onChange($event); config.value = $event\"\n [min]=\"config.min\"\n [max]=\"config.max\"\n [step]=\"config.step\"\n [allowCustomValue]=\"config.allowCustomValue\"\n >\n </app-config-slider>\n\n <button\n *ngSwitchCase=\"'button'\"\n class=\"w-100\"\n (click)=\"config.onClick()\"\n mat-button\n mat-stroked-button\n >\n {{ config.label }}\n </button>\n\n <input\n *ngSwitchCase=\"'color'\"\n id=\"item-config-field\"\n type=\"color\"\n [value]=\"config.color\"\n (input)=\"\n config.onChange($event.target.value);\n config.color = $event.target.value\n \"\n />\n\n <div *ngSwitchCase=\"'rangeSlider'\" class=\"range-slider\">\n <div class=\"range-slider-inputs d-flex align-items-center\">\n <div class=\"range-slider-side\">\n <mat-checkbox\n [(ngModel)]=\"config.enableMin\"\n (change)=\"config.setEnableMin($event.checked)\"\n ></mat-checkbox>\n <input\n type=\"number\"\n placeholder=\"Min\"\n class=\"form-control form-control-sm\"\n [(ngModel)]=\"config.value\"\n (input)=\"\n config.value = $event.target.value; config.onChange(config)\n \"\n [step]=\"config.step\"\n />\n </div>\n <div class=\"range-slider-side\">\n <mat-checkbox\n [(ngModel)]=\"config.enableMax\"\n (change)=\"config.setEnableMax($event.checked)\"\n ></mat-checkbox>\n <input\n type=\"number\"\n placeholder=\"Max\"\n class=\"form-control form-control-sm\"\n [(ngModel)]=\"config.highValue\"\n (input)=\"\n config.highValue = $event.target.value;\n config.onChange(config)\n \"\n [step]=\"config.step\"\n />\n </div>\n </div>\n </div>\n\n <select\n *ngSwitchCase=\"'select'\"\n id=\"item-config-field\"\n class=\"w-100\"\n [value]=\"config.value ?? config.options[0]\"\n (change)=\"config.onChange($event.target.value)\"\n >\n <option\n *ngFor=\"let singleOption of config.options\"\n [value]=\"singleOption\"\n >\n {{ singleOption }}\n </option>\n </select>\n </div>\n </div>\n <!-- Config types END -->\n </ng-container>\n </div>\n</ng-template>\n", styles: [".phoenix-menu-item{width:100%;padding:.6rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);font-size:.8rem;transition:all .5s;display:flex;justify-content:space-between;align-items:center}.phoenix-menu-item-left{display:flex;justify-content:flex-start;min-width:0;padding-right:.5rem;overflow:hidden}.phoenix-menu-item-left .item-name{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.phoenix-menu-item-left .item-icon{margin-right:.2rem}.phoenix-menu-item-right{display:flex;justify-content:flex-end}.phoenix-menu-item-right .item-expand.expanded{transform:scaleY(-1)}.phoenix-menu-item-right .item-settings{margin-right:.2rem}@media screen and (max-width:768px){.phoenix-menu-item{font-size:.75rem;padding:.5rem}}.phoenix-menu-item-compact{flex:1;min-width:0;color:var(--phoenix-text-color)}.phoenix-menu-item-compact .compact-option-button{width:100%;display:flex;flex-direction:column;align-items:center;gap:.15rem;padding:.3rem .2rem;color:inherit;border-radius:.3rem;transition:all .4s}.phoenix-menu-item-compact .compact-option-button:hover{background:var(--phoenix-options-icon-bg);cursor:pointer}.phoenix-menu-item-compact .compact-option-button .compact-option-label{font-size:.65rem;line-height:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.phoenix-menu-options-bar{display:flex;align-items:stretch;gap:.25rem;padding:.25rem .4rem;background:var(--phoenix-background-color-secondary)}.phoenix-menu-options-bar app-phoenix-menu-item{display:flex;flex:1;min-width:0}.phoenix-menu-item .item-config-backdrop,.phoenix-menu-item-compact .item-config-backdrop{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:110}.phoenix-menu-item .item-config,.phoenix-menu-item-compact .item-config{position:absolute;right:100%;width:14rem;padding:.5rem;background:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color-secondary);box-shadow:var(--phoenix-box-shadow);display:flex;flex-direction:column;z-index:120;max-height:60vh;overflow-y:auto;font-size:.8rem}.phoenix-menu-item .item-config::-webkit-scrollbar,.phoenix-menu-item-compact .item-config::-webkit-scrollbar{width:4px}.phoenix-menu-item .item-config::-webkit-scrollbar-thumb,.phoenix-menu-item-compact .item-config::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}.phoenix-menu-item .item-config>*,.phoenix-menu-item-compact .item-config>*{margin-bottom:.4rem}.phoenix-menu-item .item-config>*:last-child,.phoenix-menu-item-compact .item-config>*:last-child{margin-bottom:0}.phoenix-menu-item .item-config .item-config-single,.phoenix-menu-item-compact .item-config .item-config-single{display:flex;flex-direction:row}.phoenix-menu-item .item-config .item-config-single .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single .item-config-label{width:30%}.phoenix-menu-item .item-config .item-config-single .item-config-data,.phoenix-menu-item-compact .item-config .item-config-single .item-config-data{flex-grow:1;padding-left:.5rem;min-width:0}.phoenix-menu-item .item-config .item-config-single.range-slider-row,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row{align-items:center}.phoenix-menu-item .item-config .item-config-single.range-slider-row .item-config-label,.phoenix-menu-item-compact .item-config .item-config-single.range-slider-row .item-config-label{width:auto;min-width:1.6rem;flex-shrink:0;margin-bottom:0}.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{display:inline-block;width:1.3rem;height:1.3rem;padding:.23rem;transition:all .4s}.phoenix-menu-item .icon-wrapper.icon-button:hover,.phoenix-menu-item-compact .icon-wrapper.icon-button:hover{background:var(--phoenix-options-icon-bg);border-radius:40%;cursor:pointer}.phoenix-menu-item .icon-wrapper svg,.phoenix-menu-item-compact .icon-wrapper svg{width:100%;height:100%;vertical-align:top}.phoenix-menu-item .mat-slide-toggle-bar,.phoenix-menu-item-compact .mat-slide-toggle-bar{width:30px!important}.phoenix-menu-item .mat-slide-toggle-thumb,.phoenix-menu-item-compact .mat-slide-toggle-thumb{width:15px!important;height:15px!important;position:absolute;top:2px}.phoenix-menu-item .mat-slider-horizontal,.phoenix-menu-item-compact .mat-slider-horizontal{min-width:0;width:100%;height:20px}.phoenix-menu-item .mat-slider-horizontal .mat-slider-wrapper,.phoenix-menu-item-compact .mat-slider-horizontal .mat-slider-wrapper{top:10px}.phoenix-menu-item label.mat-checkbox-layout,.phoenix-menu-item-compact label.mat-checkbox-layout{margin:0}@media screen and (max-width:768px){.phoenix-menu-item .icon-wrapper,.phoenix-menu-item-compact .icon-wrapper{width:1rem;height:1rem;padding:.15rem}}.phoenix-menu-children{margin-left:.5rem;border-left:1px solid var(--phoenix-accent)}.range-slider .range-slider-inputs{gap:4px}.range-slider .range-slider-side{display:flex;align-items:center;flex:1;gap:3px;min-width:0}.range-slider .range-slider-side mat-checkbox{flex-shrink:0;--mdc-checkbox-state-layer-size: 24px}.range-slider .range-slider-side input[type=number]{min-width:0;width:100%;padding:.15rem .25rem;font-size:.75rem;appearance:textfield;-moz-appearance:textfield}.range-slider .range-slider-side input[type=number]::-webkit-outer-spin-button,.range-slider .range-slider-side input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
|
|
536
537
|
}], () => [{ type: i0.ChangeDetectorRef }], { currentNode: [{
|
|
537
538
|
type: Input
|
|
538
539
|
}], phoenixMenuItem: [{
|
|
@@ -664,11 +665,11 @@ class PhoenixMenuComponent {
|
|
|
664
665
|
} if (rf & 2) {
|
|
665
666
|
i0.ɵɵadvance(2);
|
|
666
667
|
i0.ɵɵproperty("currentNode", ctx.rootNode);
|
|
667
|
-
} }, dependencies: [i2$2.MatIcon, PhoenixMenuItemComponent], styles: ["[_nghost-%COMP%]{width:15rem;max-width:45%;position:absolute;top:5rem;right:1rem}#phoenixMenu[_ngcontent-%COMP%]{background:var(--phoenix-background-color-secondary);max-height:
|
|
668
|
+
} }, dependencies: [i2$2.MatIcon, PhoenixMenuItemComponent], styles: ["[_nghost-%COMP%]{width:15rem;max-width:45%;position:absolute;top:5rem;right:1rem}#phoenixMenu[_ngcontent-%COMP%]{background:var(--phoenix-background-color-secondary);max-height:calc(100vh - 8.5rem);overflow-y:auto;box-shadow:var(--phoenix-box-shadow);z-index:100}#phoenixMenu[_ngcontent-%COMP%]::-webkit-scrollbar{width:4px}#phoenixMenu[_ngcontent-%COMP%]::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}@media screen and (max-width:768px){#phoenixMenu[_ngcontent-%COMP%]{top:4rem}}.shortcuts-button-wrapper[_ngcontent-%COMP%]{text-align:right;pointer-events:auto}.shortcuts-btn[_ngcontent-%COMP%]{background-color:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);border:none;padding:5px 10px;border-radius:3px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--phoenix-box-shadow);transition:background-color .2s ease;font-family:inherit;font-size:.8rem}.shortcuts-btn[_ngcontent-%COMP%]:hover{background-color:var(--phoenix-menu-item-hover-color, #444)}"] });
|
|
668
669
|
}
|
|
669
670
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PhoenixMenuComponent, [{
|
|
670
671
|
type: Component,
|
|
671
|
-
args: [{ standalone: false, selector: 'app-phoenix-menu', template: "<div class=\"phoenix-menu-drag-container\">\n <div id=\"phoenixMenu\">\n <app-phoenix-menu-item [currentNode]=\"rootNode\"></app-phoenix-menu-item>\n </div>\n</div>\n<div class=\"shortcuts-button-wrapper mt-2\">\n <button class=\"shortcuts-btn\" (click)=\"openShortcutsDialog()\">\n <mat-icon\n style=\"font-size: 16px; width: 16px; height: 16px; vertical-align: middle\"\n >keyboard</mat-icon\n >\n <span style=\"vertical-align: middle\">Shortcuts</span>\n </button>\n</div>\n", styles: [":host{width:15rem;max-width:45%;position:absolute;top:5rem;right:1rem}#phoenixMenu{background:var(--phoenix-background-color-secondary);max-height:
|
|
672
|
+
args: [{ standalone: false, selector: 'app-phoenix-menu', template: "<div class=\"phoenix-menu-drag-container\">\n <div id=\"phoenixMenu\">\n <app-phoenix-menu-item [currentNode]=\"rootNode\"></app-phoenix-menu-item>\n </div>\n</div>\n<div class=\"shortcuts-button-wrapper mt-2\">\n <button class=\"shortcuts-btn\" (click)=\"openShortcutsDialog()\">\n <mat-icon\n style=\"font-size: 16px; width: 16px; height: 16px; vertical-align: middle\"\n >keyboard</mat-icon\n >\n <span style=\"vertical-align: middle\">Shortcuts</span>\n </button>\n</div>\n", styles: [":host{width:15rem;max-width:45%;position:absolute;top:5rem;right:1rem}#phoenixMenu{background:var(--phoenix-background-color-secondary);max-height:calc(100vh - 8.5rem);overflow-y:auto;box-shadow:var(--phoenix-box-shadow);z-index:100}#phoenixMenu::-webkit-scrollbar{width:4px}#phoenixMenu::-webkit-scrollbar-thumb{background:var(--phoenix-text-color-secondary, #999);border-radius:4px}@media screen and (max-width:768px){#phoenixMenu{top:4rem}}.shortcuts-button-wrapper{text-align:right;pointer-events:auto}.shortcuts-btn{background-color:var(--phoenix-background-color-secondary);color:var(--phoenix-text-color);border:none;padding:5px 10px;border-radius:3px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:var(--phoenix-box-shadow);transition:background-color .2s ease;font-family:inherit;font-size:.8rem}.shortcuts-btn:hover{background-color:var(--phoenix-menu-item-hover-color, #444)}\n"] }]
|
|
672
673
|
}], () => [{ type: i1$1.MatDialog }], { rootNode: [{
|
|
673
674
|
type: Input
|
|
674
675
|
}] }); })();
|
|
@@ -893,7 +894,7 @@ class EventDisplayService extends EventDisplay {
|
|
|
893
894
|
}]
|
|
894
895
|
}], () => [{ type: i0.NgZone }], null); })();
|
|
895
896
|
|
|
896
|
-
const _c0$
|
|
897
|
+
const _c0$e = a0 => ({ disabled: a0 });
|
|
897
898
|
const _c1$6 = a0 => ({ "active-icon": a0 });
|
|
898
899
|
class MenuToggleComponent {
|
|
899
900
|
icon;
|
|
@@ -908,7 +909,7 @@ class MenuToggleComponent {
|
|
|
908
909
|
i0.ɵɵelement(2, "use");
|
|
909
910
|
i0.ɵɵelementEnd()();
|
|
910
911
|
} if (rf & 2) {
|
|
911
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(6, _c0$
|
|
912
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(6, _c0$e, ctx.disabled))("matTooltip", ctx.tooltip);
|
|
912
913
|
i0.ɵɵadvance();
|
|
913
914
|
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(8, _c1$6, ctx.active));
|
|
914
915
|
i0.ɵɵadvance();
|
|
@@ -1185,7 +1186,7 @@ class AutoRotateComponent {
|
|
|
1185
1186
|
}], () => [{ type: EventDisplayService }], null); })();
|
|
1186
1187
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AutoRotateComponent, { className: "AutoRotateComponent", filePath: "components/ui-menu/auto-rotate/auto-rotate.component.ts", lineNumber: 10 }); })();
|
|
1187
1188
|
|
|
1188
|
-
const _c0$
|
|
1189
|
+
const _c0$d = ["overlayWindow"];
|
|
1189
1190
|
const _c1$5 = ["overlayCard"];
|
|
1190
1191
|
const _c2$2 = ["resizeHandleCorner"];
|
|
1191
1192
|
const _c3$1 = ["*"];
|
|
@@ -1237,7 +1238,7 @@ function OverlayComponent_div_3_Template(rf, ctx) { if (rf & 1) {
|
|
|
1237
1238
|
function OverlayComponent_span_4_Template(rf, ctx) { if (rf & 1) {
|
|
1238
1239
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
1239
1240
|
i0.ɵɵelementStart(0, "span", 13, 1);
|
|
1240
|
-
i0.ɵɵlistener("
|
|
1241
|
+
i0.ɵɵlistener("pointerdown", function OverlayComponent_span_4_Template_span_pointerdown_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onResizeStart($event)); })("mousedown", function OverlayComponent_span_4_Template_span_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); })("touchstart", function OverlayComponent_span_4_Template_span_touchstart_0_listener($event) { i0.ɵɵrestoreView(_r4); return i0.ɵɵresetView($event.stopPropagation()); });
|
|
1241
1242
|
i0.ɵɵelementEnd();
|
|
1242
1243
|
} if (rf & 2) {
|
|
1243
1244
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -1250,6 +1251,7 @@ let maxZIndex = 100;
|
|
|
1250
1251
|
class OverlayComponent {
|
|
1251
1252
|
eventDisplay;
|
|
1252
1253
|
elementRef;
|
|
1254
|
+
ngZone;
|
|
1253
1255
|
/** Title of the overlay. */
|
|
1254
1256
|
overlayTitle;
|
|
1255
1257
|
/** If the overlay is open or not. */
|
|
@@ -1275,8 +1277,6 @@ class OverlayComponent {
|
|
|
1275
1277
|
showBody = true;
|
|
1276
1278
|
/** Aspect ratio of the overlay view. */
|
|
1277
1279
|
aspectRatio = window.innerWidth / window.innerHeight;
|
|
1278
|
-
/** Bound resize handler for cleanup. */
|
|
1279
|
-
resizeHandler = () => this.resetHandlePosition();
|
|
1280
1280
|
// ********************************************************************************
|
|
1281
1281
|
// * Below code is specific to the overlay resize feature. (LOOK INTO CSS RESIZE) *
|
|
1282
1282
|
// ********************************************************************************
|
|
@@ -1290,9 +1290,12 @@ class OverlayComponent {
|
|
|
1290
1290
|
MIN_RES_WIDTH = 300;
|
|
1291
1291
|
/** Minimum resizable height */
|
|
1292
1292
|
MIN_RES_HEIGHT = 100;
|
|
1293
|
-
|
|
1293
|
+
/** The resize currently being dragged, or `null` if there is none. */
|
|
1294
|
+
resizeSession = null;
|
|
1295
|
+
constructor(eventDisplay, elementRef, ngZone) {
|
|
1294
1296
|
this.eventDisplay = eventDisplay;
|
|
1295
1297
|
this.elementRef = elementRef;
|
|
1298
|
+
this.ngZone = ngZone;
|
|
1296
1299
|
}
|
|
1297
1300
|
ngOnInit() { }
|
|
1298
1301
|
toggleBodyAndEmit() {
|
|
@@ -1310,95 +1313,166 @@ class OverlayComponent {
|
|
|
1310
1313
|
pane.style.zIndex = maxZIndex.toString();
|
|
1311
1314
|
}
|
|
1312
1315
|
}
|
|
1313
|
-
/**
|
|
1314
|
-
* Move the resizable handle to the bottom right after the component is created.
|
|
1315
|
-
*/
|
|
1316
1316
|
ngAfterViewInit() {
|
|
1317
1317
|
this.bringToFront();
|
|
1318
|
-
if (this.resizable) {
|
|
1319
|
-
const resizeHandleElement = this.resizeHandleCorner.nativeElement;
|
|
1320
|
-
resizeHandleElement.style.bottom = '0';
|
|
1321
|
-
resizeHandleElement.style.right = '0';
|
|
1322
|
-
new ResizeSensor(this.overlayCard.nativeElement, () => {
|
|
1323
|
-
this.resetHandlePosition();
|
|
1324
|
-
});
|
|
1325
|
-
window.addEventListener('resize', this.resizeHandler);
|
|
1326
|
-
}
|
|
1327
1318
|
}
|
|
1328
1319
|
/**
|
|
1329
|
-
* Clean up
|
|
1320
|
+
* Clean up any resize still in progress when the component is destroyed.
|
|
1330
1321
|
*/
|
|
1331
1322
|
ngOnDestroy() {
|
|
1332
|
-
|
|
1323
|
+
this.stopResize();
|
|
1333
1324
|
}
|
|
1334
1325
|
/**
|
|
1335
|
-
*
|
|
1326
|
+
* Start resizing the overlay card.
|
|
1327
|
+
*
|
|
1328
|
+
* The pointer is captured by the handle so that every subsequent move and,
|
|
1329
|
+
* crucially, the closing `pointerup` are delivered to us even if the cursor
|
|
1330
|
+
* leaves the handle or the window. Without the capture a fast drag can end
|
|
1331
|
+
* outside the handle and leave the overlay glued to the cursor.
|
|
1332
|
+
* @param event Pointer event that started the resize.
|
|
1336
1333
|
*/
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
const dragRect = resizeHandleElement.getBoundingClientRect();
|
|
1341
|
-
const overlayRect = overlayCardElement.getBoundingClientRect();
|
|
1342
|
-
const width = dragRect.left - overlayRect.left + dragRect.width;
|
|
1343
|
-
let height = dragRect.top - overlayRect.top + dragRect.height;
|
|
1344
|
-
this.setHandleTransform(overlayRect, dragRect);
|
|
1345
|
-
if (width > this.MIN_RES_WIDTH && height > this.MIN_RES_HEIGHT) {
|
|
1346
|
-
if (this.keepAspectRatioFixed) {
|
|
1347
|
-
height = width / this.aspectRatio;
|
|
1348
|
-
}
|
|
1349
|
-
if (this.overlayWindow?.nativeElement) {
|
|
1350
|
-
const oldratioW = width / this.overlayWindow.nativeElement.width;
|
|
1351
|
-
const oldratioH = height / this.overlayWindow.nativeElement.height;
|
|
1352
|
-
this.eventDisplay
|
|
1353
|
-
.getThreeManager()
|
|
1354
|
-
.getOverlayRenderer()
|
|
1355
|
-
.setSize(width, height);
|
|
1356
|
-
this.eventDisplay
|
|
1357
|
-
.getThreeManager()
|
|
1358
|
-
.syncOverlayViewPort(oldratioW, oldratioH);
|
|
1359
|
-
}
|
|
1360
|
-
else {
|
|
1361
|
-
// Fallback for generic content that does not have a 3D canvas
|
|
1362
|
-
this.overlayCard.nativeElement.style.width = width + 'px';
|
|
1363
|
-
this.overlayCard.nativeElement.style.height = height + 'px';
|
|
1364
|
-
const contentWrapper = this.overlayCard.nativeElement.querySelector('.overlay-card-content');
|
|
1365
|
-
if (contentWrapper) {
|
|
1366
|
-
contentWrapper.style.flex = '1';
|
|
1367
|
-
contentWrapper.style.overflow = 'hidden';
|
|
1368
|
-
contentWrapper.style.maxHeight = 'none';
|
|
1369
|
-
const contentBody = contentWrapper.firstElementChild;
|
|
1370
|
-
if (contentBody) {
|
|
1371
|
-
contentBody.style.width = '100%';
|
|
1372
|
-
contentBody.style.height = '100%';
|
|
1373
|
-
contentBody.style.maxWidth = 'none';
|
|
1374
|
-
contentBody.style.maxHeight = 'none';
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1334
|
+
onResizeStart(event) {
|
|
1335
|
+
if (!this.resizable || this.resizeSession) {
|
|
1336
|
+
return;
|
|
1378
1337
|
}
|
|
1338
|
+
event.preventDefault();
|
|
1339
|
+
this.bringToFront();
|
|
1340
|
+
// The 3D overlay sizes its canvas, everything else sizes the whole card,
|
|
1341
|
+
// so measure whichever one the drag is going to act on.
|
|
1342
|
+
const startRect = (this.overlayWindow?.nativeElement ?? this.overlayCard.nativeElement).getBoundingClientRect();
|
|
1343
|
+
this.resizeSession = {
|
|
1344
|
+
pointerId: event.pointerId,
|
|
1345
|
+
startX: event.clientX,
|
|
1346
|
+
startY: event.clientY,
|
|
1347
|
+
startWidth: startRect.width,
|
|
1348
|
+
startHeight: startRect.height,
|
|
1349
|
+
};
|
|
1350
|
+
const handle = this.resizeHandleCorner.nativeElement;
|
|
1351
|
+
try {
|
|
1352
|
+
handle.setPointerCapture?.(event.pointerId);
|
|
1353
|
+
}
|
|
1354
|
+
catch {
|
|
1355
|
+
// Capturing is best effort; the listeners below still end the resize.
|
|
1356
|
+
}
|
|
1357
|
+
// Resizing only writes to the DOM and the renderer, so it does not need to
|
|
1358
|
+
// trigger change detection on every pointer move.
|
|
1359
|
+
this.ngZone.runOutsideAngular(() => {
|
|
1360
|
+
handle.addEventListener('pointermove', this.onResizeMove);
|
|
1361
|
+
handle.addEventListener('pointerup', this.onResizeEnd);
|
|
1362
|
+
handle.addEventListener('pointercancel', this.onResizeEnd);
|
|
1363
|
+
handle.addEventListener('lostpointercapture', this.onResizeEnd);
|
|
1364
|
+
document.addEventListener('keydown', this.onResizeKeyDown);
|
|
1365
|
+
});
|
|
1379
1366
|
}
|
|
1367
|
+
/** Resize the overlay to follow the pointer. */
|
|
1368
|
+
onResizeMove = (event) => {
|
|
1369
|
+
const session = this.resizeSession;
|
|
1370
|
+
if (!session || event.pointerId !== session.pointerId) {
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
// The button can be released where the page never sees it, e.g. outside the
|
|
1374
|
+
// window. Noticing that the button is gone stops the overlay from staying
|
|
1375
|
+
// glued to the cursor.
|
|
1376
|
+
if (event.pointerType === 'mouse' && event.buttons === 0) {
|
|
1377
|
+
this.stopResize();
|
|
1378
|
+
return;
|
|
1379
|
+
}
|
|
1380
|
+
event.preventDefault();
|
|
1381
|
+
const width = Math.max(this.MIN_RES_WIDTH, session.startWidth + (event.clientX - session.startX));
|
|
1382
|
+
const height = Math.max(this.MIN_RES_HEIGHT, session.startHeight + (event.clientY - session.startY));
|
|
1383
|
+
this.applySize(width, this.keepAspectRatioFixed ? width / this.aspectRatio : height);
|
|
1384
|
+
};
|
|
1385
|
+
/** End the resize once the pointer is released, cancelled or lost. */
|
|
1386
|
+
onResizeEnd = (event) => {
|
|
1387
|
+
if (this.resizeSession &&
|
|
1388
|
+
event.pointerId !== this.resizeSession.pointerId) {
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
this.stopResize();
|
|
1392
|
+
};
|
|
1393
|
+
/** Abandon the resize and restore the original size on Escape. */
|
|
1394
|
+
onResizeKeyDown = (event) => {
|
|
1395
|
+
if (event.key !== 'Escape' || !this.resizeSession) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
const { startWidth, startHeight } = this.resizeSession;
|
|
1399
|
+
this.stopResize();
|
|
1400
|
+
if (startWidth > 0 && startHeight > 0) {
|
|
1401
|
+
this.applySize(startWidth, startHeight);
|
|
1402
|
+
}
|
|
1403
|
+
};
|
|
1380
1404
|
/**
|
|
1381
|
-
*
|
|
1405
|
+
* Stop the resize in progress, if any, releasing the pointer and detaching
|
|
1406
|
+
* every listener added when it started.
|
|
1382
1407
|
*/
|
|
1383
|
-
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1408
|
+
stopResize() {
|
|
1409
|
+
const session = this.resizeSession;
|
|
1410
|
+
if (!session) {
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1413
|
+
this.resizeSession = null;
|
|
1414
|
+
document.removeEventListener('keydown', this.onResizeKeyDown);
|
|
1415
|
+
const handle = this.resizeHandleCorner?.nativeElement;
|
|
1416
|
+
if (!handle) {
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
handle.removeEventListener('pointermove', this.onResizeMove);
|
|
1420
|
+
handle.removeEventListener('pointerup', this.onResizeEnd);
|
|
1421
|
+
handle.removeEventListener('pointercancel', this.onResizeEnd);
|
|
1422
|
+
handle.removeEventListener('lostpointercapture', this.onResizeEnd);
|
|
1423
|
+
try {
|
|
1424
|
+
if (handle.hasPointerCapture?.(session.pointerId)) {
|
|
1425
|
+
handle.releasePointerCapture(session.pointerId);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
catch {
|
|
1429
|
+
// The pointer may already be gone; nothing left to release.
|
|
1430
|
+
}
|
|
1388
1431
|
}
|
|
1389
1432
|
/**
|
|
1390
|
-
*
|
|
1391
|
-
* @param
|
|
1392
|
-
* @param
|
|
1433
|
+
* Resize the overlay content to the given size.
|
|
1434
|
+
* @param width New width of the overlay content in pixels.
|
|
1435
|
+
* @param height New height of the overlay content in pixels.
|
|
1393
1436
|
*/
|
|
1394
|
-
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1437
|
+
applySize(width, height) {
|
|
1438
|
+
const canvas = this.overlayWindow?.nativeElement;
|
|
1439
|
+
if (canvas) {
|
|
1440
|
+
const oldratioW = width / canvas.width;
|
|
1441
|
+
const oldratioH = height / canvas.height;
|
|
1442
|
+
this.eventDisplay
|
|
1443
|
+
.getThreeManager()
|
|
1444
|
+
.getOverlayRenderer()
|
|
1445
|
+
.setSize(width, height);
|
|
1446
|
+
this.eventDisplay
|
|
1447
|
+
.getThreeManager()
|
|
1448
|
+
.syncOverlayViewPort(oldratioW, oldratioH);
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
// Fallback for generic content that does not have a 3D canvas
|
|
1452
|
+
const overlayCardElement = this.overlayCard.nativeElement;
|
|
1453
|
+
overlayCardElement.style.width = width + 'px';
|
|
1454
|
+
overlayCardElement.style.height = height + 'px';
|
|
1455
|
+
const contentWrapper = overlayCardElement.querySelector('.overlay-card-content');
|
|
1456
|
+
if (contentWrapper) {
|
|
1457
|
+
contentWrapper.style.flex = '1';
|
|
1458
|
+
contentWrapper.style.overflow = 'auto';
|
|
1459
|
+
contentWrapper.style.maxHeight = 'none';
|
|
1460
|
+
const contentBody = contentWrapper.firstElementChild;
|
|
1461
|
+
if (contentBody) {
|
|
1462
|
+
// Fill the card when there is room to spare, but keep the natural
|
|
1463
|
+
// height when there is not so the wrapper can scroll instead of
|
|
1464
|
+
// clipping the content.
|
|
1465
|
+
contentBody.style.width = '100%';
|
|
1466
|
+
contentBody.style.height = 'auto';
|
|
1467
|
+
contentBody.style.minHeight = '100%';
|
|
1468
|
+
contentBody.style.maxWidth = 'none';
|
|
1469
|
+
contentBody.style.maxHeight = 'none';
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1398
1472
|
}
|
|
1399
|
-
static ɵfac = function OverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || OverlayComponent)(i0.ɵɵdirectiveInject(EventDisplayService), i0.ɵɵdirectiveInject(i0.ElementRef)); };
|
|
1473
|
+
static ɵfac = function OverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || OverlayComponent)(i0.ɵɵdirectiveInject(EventDisplayService), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.NgZone)); };
|
|
1400
1474
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: OverlayComponent, selectors: [["app-overlay"]], contentQueries: function OverlayComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) {
|
|
1401
|
-
i0.ɵɵcontentQuery(dirIndex, _c0$
|
|
1475
|
+
i0.ɵɵcontentQuery(dirIndex, _c0$d, 5);
|
|
1402
1476
|
} if (rf & 2) {
|
|
1403
1477
|
let _t;
|
|
1404
1478
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.overlayWindow = _t.first);
|
|
@@ -1409,7 +1483,7 @@ class OverlayComponent {
|
|
|
1409
1483
|
let _t;
|
|
1410
1484
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.overlayCard = _t.first);
|
|
1411
1485
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.resizeHandleCorner = _t.first);
|
|
1412
|
-
} }, inputs: { overlayTitle: "overlayTitle", active: "active", icon: "icon", resizable: "resizable", transparentBody: "transparentBody", keepAspectRatioFixed: "keepAspectRatioFixed" }, standalone: false, ngContentSelectors: _c3$1, decls: 5, vars: 4, consts: [["overlayCard", ""], ["resizeHandleCorner", ""], ["cdkDrag", "", "cdkDragRootElement", ".cdk-overlay-pane", "cdkDragBoundary", "body", 1, "overlay-card", "card", 3, "mousedown", "touchstart", "hidden"], ["class", "card-header d-flex justify-content-between", "cdkDragHandle", "", 3, "ngClass", 4, "ngIf"], ["class", "overlay-card-content", 3, "ngClass", 4, "ngIf"], ["class", "resize-handle corner", "
|
|
1486
|
+
} }, inputs: { overlayTitle: "overlayTitle", active: "active", icon: "icon", resizable: "resizable", transparentBody: "transparentBody", keepAspectRatioFixed: "keepAspectRatioFixed" }, standalone: false, ngContentSelectors: _c3$1, decls: 5, vars: 4, consts: [["overlayCard", ""], ["resizeHandleCorner", ""], ["cdkDrag", "", "cdkDragRootElement", ".cdk-overlay-pane", "cdkDragBoundary", "body", 1, "overlay-card", "card", 3, "mousedown", "touchstart", "hidden"], ["class", "card-header d-flex justify-content-between", "cdkDragHandle", "", 3, "ngClass", 4, "ngIf"], ["class", "overlay-card-content", 3, "ngClass", 4, "ngIf"], ["class", "resize-handle corner", 3, "hidden", "pointerdown", "mousedown", "touchstart", 4, "ngIf"], ["cdkDragHandle", "", 1, "card-header", "d-flex", "justify-content-between", 3, "ngClass"], ["class", "align-self-center card-icon", 4, "ngIf"], [1, "align-self-center", "m-0", "px-2"], ["matTooltip", "Expand / Collapse", "matTooltipPosition", "right", 1, "align-self-center", "card-icon", "btn-blank", "expandCollapse", 3, "click", "ngClass"], ["href", "assets/icons/expand.svg#expand"], [1, "align-self-center", "card-icon"], [1, "overlay-card-content", 3, "ngClass"], [1, "resize-handle", "corner", 3, "pointerdown", "mousedown", "touchstart", "hidden"]], template: function OverlayComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1413
1487
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
1414
1488
|
i0.ɵɵprojectionDef();
|
|
1415
1489
|
i0.ɵɵelementStart(0, "div", 2, 0);
|
|
@@ -1424,12 +1498,12 @@ class OverlayComponent {
|
|
|
1424
1498
|
i0.ɵɵproperty("ngIf", ctx.showBody);
|
|
1425
1499
|
i0.ɵɵadvance();
|
|
1426
1500
|
i0.ɵɵproperty("ngIf", ctx.resizable);
|
|
1427
|
-
} }, dependencies: [i2.NgClass, i2.NgIf, i3$2.CdkDrag, i3$2.CdkDragHandle, i3$1.MatTooltip], styles: [".overlay-card.card{color:var(--phoenix-text-color);background:none;max-width:95vw;font-size:12px;min-width:300px;height:auto;display:flex;flex-direction:column;box-shadow:none;border:none;position:relative;z-index:200}.overlay-card.card .card-header{width:12rem;background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);padding:.4rem .8rem;border-radius:10px;border:none;cursor:move;text-align:center;transition:all .2s}.overlay-card.card .card-header.with-body{border-bottom-left-radius:0;border-bottom-right-radius:0}.overlay-card.card .card-header .card-icon{display:flex;height:.7rem;width:.7rem}.overlay-card.card .card-header h5{font-size:.9rem}.overlay-card.card .card-header .expandCollapse{cursor:pointer;transition:all .2s}.overlay-card.card .card-header .expandCollapse.expand{transform:scaleY(-1)}.overlay-card.card .card-header .expandCollapse svg{width:100%;height:100%}.overlay-card.card .overlay-card-content{background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);border-radius:0 10px 10px;overflow:auto;height:100%;max-height:40vh}.overlay-card.card .overlay-card-content.transparent-bg{background:none}.overlay-card.card .list-group{color:var(--phoenix-text-color-secondary);background:var(--phoenix-background-color-secondary);max-height:40vh;overflow:auto}.overlay-card.card .list-group .list-group-item{background-color:var(--phoenix-background-color-secondary);border-color:var(--phoenix-border)}.overlay-card.card .resize-handle{width:1rem;height:1rem;cursor:nwse-resize;position:absolute}.overlay-card.card .resize-handle.corner{border-right:.2rem solid var(--phoenix-text-color);border-bottom:.2rem solid var(--phoenix-text-color)}\n"], encapsulation: 2 });
|
|
1501
|
+
} }, dependencies: [i2.NgClass, i2.NgIf, i3$2.CdkDrag, i3$2.CdkDragHandle, i3$1.MatTooltip], styles: [".overlay-card.card{color:var(--phoenix-text-color);background:none;max-width:95vw;font-size:12px;min-width:300px;height:auto;display:flex;flex-direction:column;box-shadow:none;border:none;position:relative;z-index:200}.overlay-card.card .card-header{width:12rem;background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);padding:.4rem .8rem;border-radius:10px;border:none;cursor:move;text-align:center;transition:all .2s}.overlay-card.card .card-header.with-body{border-bottom-left-radius:0;border-bottom-right-radius:0}.overlay-card.card .card-header .card-icon{display:flex;height:.7rem;width:.7rem}.overlay-card.card .card-header h5{font-size:.9rem}.overlay-card.card .card-header .expandCollapse{cursor:pointer;transition:all .2s}.overlay-card.card .card-header .expandCollapse.expand{transform:scaleY(-1)}.overlay-card.card .card-header .expandCollapse svg{width:100%;height:100%}.overlay-card.card .overlay-card-content{background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);border-radius:0 10px 10px;overflow:auto;height:100%;max-height:40vh}.overlay-card.card .overlay-card-content.transparent-bg{background:none}.overlay-card.card .list-group{color:var(--phoenix-text-color-secondary);background:var(--phoenix-background-color-secondary);max-height:40vh;overflow:auto}.overlay-card.card .list-group .list-group-item{background-color:var(--phoenix-background-color-secondary);border-color:var(--phoenix-border)}.overlay-card.card .resize-handle{width:1rem;height:1rem;cursor:nwse-resize;position:absolute;bottom:0;right:0;touch-action:none}.overlay-card.card .resize-handle.corner{border-right:.2rem solid var(--phoenix-text-color);border-bottom:.2rem solid var(--phoenix-text-color)}\n"], encapsulation: 2 });
|
|
1428
1502
|
}
|
|
1429
1503
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(OverlayComponent, [{
|
|
1430
1504
|
type: Component,
|
|
1431
|
-
args: [{ standalone: false, selector: 'app-overlay', encapsulation: ViewEncapsulation.None, template: "<div\n #overlayCard\n class=\"overlay-card card\"\n [hidden]=\"!active\"\n (mousedown)=\"bringToFront()\"\n (touchstart)=\"bringToFront()\"\n cdkDrag\n cdkDragRootElement=\".cdk-overlay-pane\"\n cdkDragBoundary=\"body\"\n>\n <div\n class=\"card-header d-flex justify-content-between\"\n [ngClass]=\"{ 'with-body': showBody }\"\n cdkDragHandle\n *ngIf=\"overlayTitle\"\n >\n <div class=\"align-self-center card-icon\" *ngIf=\"icon\">\n <svg>\n <use attr.href=\"assets/icons/{{ icon }}.svg#{{ icon }}\"></use>\n </svg>\n </div>\n <h5 class=\"align-self-center m-0 px-2\">{{ overlayTitle }}</h5>\n <button\n class=\"align-self-center card-icon btn-blank expandCollapse\"\n matTooltip=\"Expand / Collapse\"\n matTooltipPosition=\"right\"\n [ngClass]=\"{ expand: showBody }\"\n (click)=\"toggleBodyAndEmit()\"\n >\n <svg>\n <use href=\"assets/icons/expand.svg#expand\"></use>\n </svg>\n </button>\n </div>\n <div\n class=\"overlay-card-content\"\n *ngIf=\"showBody\"\n [ngClass]=\"{ 'transparent-bg': transparentBody }\"\n >\n <ng-content></ng-content>\n </div>\n <!-- Making the overlay resizable -->\n <span\n #resizeHandleCorner\n class=\"resize-handle corner\"\n *ngIf=\"resizable\"\n [hidden]=\"!showBody\"\n
|
|
1432
|
-
}], () => [{ type: EventDisplayService }, { type: i0.ElementRef }], { overlayTitle: [{
|
|
1505
|
+
args: [{ standalone: false, selector: 'app-overlay', encapsulation: ViewEncapsulation.None, template: "<div\n #overlayCard\n class=\"overlay-card card\"\n [hidden]=\"!active\"\n (mousedown)=\"bringToFront()\"\n (touchstart)=\"bringToFront()\"\n cdkDrag\n cdkDragRootElement=\".cdk-overlay-pane\"\n cdkDragBoundary=\"body\"\n>\n <div\n class=\"card-header d-flex justify-content-between\"\n [ngClass]=\"{ 'with-body': showBody }\"\n cdkDragHandle\n *ngIf=\"overlayTitle\"\n >\n <div class=\"align-self-center card-icon\" *ngIf=\"icon\">\n <svg>\n <use attr.href=\"assets/icons/{{ icon }}.svg#{{ icon }}\"></use>\n </svg>\n </div>\n <h5 class=\"align-self-center m-0 px-2\">{{ overlayTitle }}</h5>\n <button\n class=\"align-self-center card-icon btn-blank expandCollapse\"\n matTooltip=\"Expand / Collapse\"\n matTooltipPosition=\"right\"\n [ngClass]=\"{ expand: showBody }\"\n (click)=\"toggleBodyAndEmit()\"\n >\n <svg>\n <use href=\"assets/icons/expand.svg#expand\"></use>\n </svg>\n </button>\n </div>\n <div\n class=\"overlay-card-content\"\n *ngIf=\"showBody\"\n [ngClass]=\"{ 'transparent-bg': transparentBody }\"\n >\n <ng-content></ng-content>\n </div>\n <!-- Making the overlay resizable -->\n <span\n #resizeHandleCorner\n class=\"resize-handle corner\"\n *ngIf=\"resizable\"\n [hidden]=\"!showBody\"\n (pointerdown)=\"onResizeStart($event)\"\n (mousedown)=\"$event.stopPropagation()\"\n (touchstart)=\"$event.stopPropagation()\"\n ></span>\n</div>\n", styles: [".overlay-card.card{color:var(--phoenix-text-color);background:none;max-width:95vw;font-size:12px;min-width:300px;height:auto;display:flex;flex-direction:column;box-shadow:none;border:none;position:relative;z-index:200}.overlay-card.card .card-header{width:12rem;background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);padding:.4rem .8rem;border-radius:10px;border:none;cursor:move;text-align:center;transition:all .2s}.overlay-card.card .card-header.with-body{border-bottom-left-radius:0;border-bottom-right-radius:0}.overlay-card.card .card-header .card-icon{display:flex;height:.7rem;width:.7rem}.overlay-card.card .card-header h5{font-size:.9rem}.overlay-card.card .card-header .expandCollapse{cursor:pointer;transition:all .2s}.overlay-card.card .card-header .expandCollapse.expand{transform:scaleY(-1)}.overlay-card.card .card-header .expandCollapse svg{width:100%;height:100%}.overlay-card.card .overlay-card-content{background:var(--phoenix-background-color-secondary);box-shadow:var(--phoenix-box-shadow);border-radius:0 10px 10px;overflow:auto;height:100%;max-height:40vh}.overlay-card.card .overlay-card-content.transparent-bg{background:none}.overlay-card.card .list-group{color:var(--phoenix-text-color-secondary);background:var(--phoenix-background-color-secondary);max-height:40vh;overflow:auto}.overlay-card.card .list-group .list-group-item{background-color:var(--phoenix-background-color-secondary);border-color:var(--phoenix-border)}.overlay-card.card .resize-handle{width:1rem;height:1rem;cursor:nwse-resize;position:absolute;bottom:0;right:0;touch-action:none}.overlay-card.card .resize-handle.corner{border-right:.2rem solid var(--phoenix-text-color);border-bottom:.2rem solid var(--phoenix-text-color)}\n"] }]
|
|
1506
|
+
}], () => [{ type: EventDisplayService }, { type: i0.ElementRef }, { type: i0.NgZone }], { overlayTitle: [{
|
|
1433
1507
|
type: Input
|
|
1434
1508
|
}], active: [{
|
|
1435
1509
|
type: Input
|
|
@@ -1451,9 +1525,9 @@ class OverlayComponent {
|
|
|
1451
1525
|
type: ContentChild,
|
|
1452
1526
|
args: ['overlayWindow']
|
|
1453
1527
|
}] }); })();
|
|
1454
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(OverlayComponent, { className: "OverlayComponent", filePath: "components/ui-menu/overlay/overlay.component.ts", lineNumber:
|
|
1528
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(OverlayComponent, { className: "OverlayComponent", filePath: "components/ui-menu/overlay/overlay.component.ts", lineNumber: 37 }); })();
|
|
1455
1529
|
|
|
1456
|
-
const _c0$
|
|
1530
|
+
const _c0$c = (a0, a1, a2) => ({ "active-object": a0, "is-cut": a1, "d-none": a2 });
|
|
1457
1531
|
function CollectionsInfoOverlayComponent_div_1_div_1_optgroup_10_option_1_Template(rf, ctx) { if (rf & 1) {
|
|
1458
1532
|
i0.ɵɵelementStart(0, "option", 17);
|
|
1459
1533
|
i0.ɵɵtext(1);
|
|
@@ -1580,7 +1654,7 @@ function CollectionsInfoOverlayComponent_div_1_table_3_tr_11_Template(rf, ctx) {
|
|
|
1580
1654
|
const object_r10 = ctx.$implicit;
|
|
1581
1655
|
const i_r12 = ctx.index;
|
|
1582
1656
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
1583
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(8, _c0$
|
|
1657
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction3(8, _c0$c, ctx_r1.activeObject && ctx_r1.activeObject.value === object_r10.uuid, object_r10.isCut, object_r10.isCut && ctx_r1.hideInvisible));
|
|
1584
1658
|
i0.ɵɵattribute("id", object_r10.uuid);
|
|
1585
1659
|
i0.ɵɵadvance(2);
|
|
1586
1660
|
i0.ɵɵtextInterpolate1("#", i_r12);
|
|
@@ -1841,7 +1915,7 @@ class CollectionsInfoComponent {
|
|
|
1841
1915
|
}], () => [{ type: i1$3.Overlay }], null); })();
|
|
1842
1916
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CollectionsInfoComponent, { className: "CollectionsInfoComponent", filePath: "components/ui-menu/collections-info/collections-info.component.ts", lineNumber: 17 }); })();
|
|
1843
1917
|
|
|
1844
|
-
const _c0$
|
|
1918
|
+
const _c0$b = a0 => ({ "active-object": a0 });
|
|
1845
1919
|
function GeometryBrowserOverlayComponent_div_1_div_1_option_8_Template(rf, ctx) { if (rf & 1) {
|
|
1846
1920
|
i0.ɵɵelementStart(0, "option", 13);
|
|
1847
1921
|
i0.ɵɵtext(1);
|
|
@@ -1896,7 +1970,7 @@ function GeometryBrowserOverlayComponent_div_1_table_3_tr_8_Template(rf, ctx) {
|
|
|
1896
1970
|
const object_r5 = ctx.$implicit;
|
|
1897
1971
|
const i_r6 = ctx.index;
|
|
1898
1972
|
const ctx_r1 = i0.ɵɵnextContext(3);
|
|
1899
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(4, _c0$
|
|
1973
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(4, _c0$b, ctx_r1.activeObject && ctx_r1.activeObject.value === object_r5.uuid));
|
|
1900
1974
|
i0.ɵɵattribute("id", object_r5.uuid);
|
|
1901
1975
|
i0.ɵɵadvance(2);
|
|
1902
1976
|
i0.ɵɵtextInterpolate1("#", i_r6);
|
|
@@ -3074,7 +3148,7 @@ class ObjectSelectionComponent {
|
|
|
3074
3148
|
}], () => [{ type: i1$3.Overlay }, { type: EventDisplayService }], null); })();
|
|
3075
3149
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ObjectSelectionComponent, { className: "ObjectSelectionComponent", filePath: "components/ui-menu/object-selection/object-selection.component.ts", lineNumber: 18 }); })();
|
|
3076
3150
|
|
|
3077
|
-
const _c0$
|
|
3151
|
+
const _c0$a = ["overlayWindow"];
|
|
3078
3152
|
class OverlayViewWindowComponent {
|
|
3079
3153
|
eventDisplay;
|
|
3080
3154
|
showOverlay = true;
|
|
@@ -3126,7 +3200,7 @@ class OverlayViewWindowComponent {
|
|
|
3126
3200
|
}
|
|
3127
3201
|
static ɵfac = function OverlayViewWindowComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || OverlayViewWindowComponent)(i0.ɵɵdirectiveInject(EventDisplayService)); };
|
|
3128
3202
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: OverlayViewWindowComponent, selectors: [["app-overlay-view-window"]], viewQuery: function OverlayViewWindowComponent_Query(rf, ctx) { if (rf & 1) {
|
|
3129
|
-
i0.ɵɵviewQuery(_c0$
|
|
3203
|
+
i0.ɵɵviewQuery(_c0$a, 5);
|
|
3130
3204
|
} if (rf & 2) {
|
|
3131
3205
|
let _t;
|
|
3132
3206
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.overlayWindow = _t.first);
|
|
@@ -3214,7 +3288,7 @@ class OverlayViewComponent {
|
|
|
3214
3288
|
}], () => [{ type: i1$3.Overlay }], null); })();
|
|
3215
3289
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(OverlayViewComponent, { className: "OverlayViewComponent", filePath: "components/ui-menu/overlay-view/overlay-view.component.ts", lineNumber: 17 }); })();
|
|
3216
3290
|
|
|
3217
|
-
const _c0$
|
|
3291
|
+
const _c0$9 = a0 => ({ visible: a0 });
|
|
3218
3292
|
function TreeMenuItemComponent_ng_container_0_button_2_Template(rf, ctx) { if (rf & 1) {
|
|
3219
3293
|
const _r2 = i0.ɵɵgetCurrentView();
|
|
3220
3294
|
i0.ɵɵelementStart(0, "button", 7);
|
|
@@ -3252,7 +3326,7 @@ function TreeMenuItemComponent_ng_container_0_Template(rf, ctx) { if (rf & 1) {
|
|
|
3252
3326
|
} if (rf & 2) {
|
|
3253
3327
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
3254
3328
|
i0.ɵɵadvance();
|
|
3255
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(5, _c0$
|
|
3329
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(5, _c0$9, ctx_r2.visible));
|
|
3256
3330
|
i0.ɵɵadvance();
|
|
3257
3331
|
i0.ɵɵproperty("ngIf", ctx_r2.node.children);
|
|
3258
3332
|
i0.ɵɵadvance(2);
|
|
@@ -4241,7 +4315,7 @@ class PerformanceToggleComponent {
|
|
|
4241
4315
|
}], () => [{ type: EventDisplayService }], null); })();
|
|
4242
4316
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PerformanceToggleComponent, { className: "PerformanceToggleComponent", filePath: "components/ui-menu/performance-toggle/performance-toggle.component.ts", lineNumber: 10 }); })();
|
|
4243
4317
|
|
|
4244
|
-
const _c0$
|
|
4318
|
+
const _c0$8 = ["*"];
|
|
4245
4319
|
function UiMenuComponent_app_object_clipping_6_Template(rf, ctx) { if (rf & 1) {
|
|
4246
4320
|
i0.ɵɵelement(0, "app-object-clipping");
|
|
4247
4321
|
} }
|
|
@@ -4281,6 +4355,12 @@ function UiMenuComponent_app_make_picture_17_Template(rf, ctx) { if (rf & 1) {
|
|
|
4281
4355
|
function UiMenuComponent_app_share_link_19_Template(rf, ctx) { if (rf & 1) {
|
|
4282
4356
|
i0.ɵɵelement(0, "app-share-link");
|
|
4283
4357
|
} }
|
|
4358
|
+
function UiMenuComponent_app_histogram_panel_20_Template(rf, ctx) { if (rf & 1) {
|
|
4359
|
+
i0.ɵɵelement(0, "app-histogram-panel", 6);
|
|
4360
|
+
} if (rf & 2) {
|
|
4361
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
4362
|
+
i0.ɵɵproperty("config", ctx_r0.histogramConfig);
|
|
4363
|
+
} }
|
|
4284
4364
|
const defaultUIMenuConfig = {
|
|
4285
4365
|
showVRToggle: true,
|
|
4286
4366
|
showARToggle: true,
|
|
@@ -4299,15 +4379,17 @@ const defaultUIMenuConfig = {
|
|
|
4299
4379
|
showEtaPhiPanel: true,
|
|
4300
4380
|
showKinematicsPanel: true,
|
|
4301
4381
|
showMasterclassPanel: false,
|
|
4382
|
+
showHistogramPanel: false,
|
|
4302
4383
|
};
|
|
4303
4384
|
class UiMenuComponent {
|
|
4304
4385
|
eventDataImportOptions = Object.values(EventDataFormat);
|
|
4305
4386
|
animationPresets = defaultAnimationPresets;
|
|
4387
|
+
histogramConfig;
|
|
4306
4388
|
uiConfig = { ...defaultUIMenuConfig };
|
|
4307
4389
|
kinematicsConfig;
|
|
4308
4390
|
masterclassConfig;
|
|
4309
4391
|
static ɵfac = function UiMenuComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UiMenuComponent)(); };
|
|
4310
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UiMenuComponent, selectors: [["app-ui-menu"]], inputs: { eventDataImportOptions: "eventDataImportOptions", animationPresets: "animationPresets", uiConfig: "uiConfig", kinematicsConfig: "kinematicsConfig", masterclassConfig: "masterclassConfig" }, standalone: false, ngContentSelectors: _c0$
|
|
4392
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UiMenuComponent, selectors: [["app-ui-menu"]], inputs: { eventDataImportOptions: "eventDataImportOptions", animationPresets: "animationPresets", histogramConfig: "histogramConfig", uiConfig: "uiConfig", kinematicsConfig: "kinematicsConfig", masterclassConfig: "masterclassConfig" }, standalone: false, ngContentSelectors: _c0$8, decls: 22, vars: 15, consts: [[4, "ngIf"], [3, "animationPresets", 4, "ngIf"], [3, "uiConfig", "kinematicsConfig"], [3, "config", 4, "ngIf"], [3, "eventDataImportOptions"], [3, "animationPresets"], [3, "config"]], template: function UiMenuComponent_Template(rf, ctx) { if (rf & 1) {
|
|
4311
4393
|
i0.ɵɵprojectionDef();
|
|
4312
4394
|
i0.ɵɵelementStart(0, "app-ui-menu-wrapper");
|
|
4313
4395
|
i0.ɵɵelement(1, "app-event-selector")(2, "app-zoom-controls")(3, "app-view-options")(4, "app-auto-rotate")(5, "app-dark-theme");
|
|
@@ -4317,8 +4399,8 @@ class UiMenuComponent {
|
|
|
4317
4399
|
i0.ɵɵelement(12, "app-more-info", 2);
|
|
4318
4400
|
i0.ɵɵtemplate(13, UiMenuComponent_app_masterclass_panel_13_Template, 1, 1, "app-masterclass-panel", 3)(14, UiMenuComponent_app_performance_toggle_14_Template, 1, 0, "app-performance-toggle", 0)(15, UiMenuComponent_app_vr_toggle_15_Template, 1, 0, "app-vr-toggle", 0)(16, UiMenuComponent_app_ar_toggle_16_Template, 1, 0, "app-ar-toggle", 0)(17, UiMenuComponent_app_make_picture_17_Template, 1, 0, "app-make-picture", 0);
|
|
4319
4401
|
i0.ɵɵelement(18, "app-io-options", 4);
|
|
4320
|
-
i0.ɵɵtemplate(19, UiMenuComponent_app_share_link_19_Template, 1, 0, "app-share-link", 0);
|
|
4321
|
-
i0.ɵɵprojection(
|
|
4402
|
+
i0.ɵɵtemplate(19, UiMenuComponent_app_share_link_19_Template, 1, 0, "app-share-link", 0)(20, UiMenuComponent_app_histogram_panel_20_Template, 1, 1, "app-histogram-panel", 3);
|
|
4403
|
+
i0.ɵɵprojection(21);
|
|
4322
4404
|
i0.ɵɵelementEnd();
|
|
4323
4405
|
} if (rf & 2) {
|
|
4324
4406
|
i0.ɵɵadvance(6);
|
|
@@ -4347,15 +4429,19 @@ class UiMenuComponent {
|
|
|
4347
4429
|
i0.ɵɵproperty("eventDataImportOptions", ctx.eventDataImportOptions);
|
|
4348
4430
|
i0.ɵɵadvance();
|
|
4349
4431
|
i0.ɵɵproperty("ngIf", ctx.uiConfig.showShareLink);
|
|
4432
|
+
i0.ɵɵadvance();
|
|
4433
|
+
i0.ɵɵproperty("ngIf", ctx.uiConfig == null ? null : ctx.uiConfig.showHistogramPanel);
|
|
4350
4434
|
} }, encapsulation: 2 });
|
|
4351
4435
|
}
|
|
4352
4436
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UiMenuComponent, [{
|
|
4353
4437
|
type: Component,
|
|
4354
|
-
args: [{ standalone: false, selector: 'app-ui-menu', template: "<app-ui-menu-wrapper>\n <!-- Event selector -->\n <app-event-selector></app-event-selector>\n\n <!-- Zoom in and zoom out controls -->\n <app-zoom-controls></app-zoom-controls>\n\n <app-view-options></app-view-options>\n\n <app-auto-rotate></app-auto-rotate>\n\n <!-- Dark theme toggle -->\n <app-dark-theme></app-dark-theme>\n\n <!-- Toggle for clipping geometries -->\n <app-object-clipping\n *ngIf=\"uiConfig.showObjectClipping\"\n ></app-object-clipping>\n\n <!-- Main view toggle -->\n <app-main-view-toggle></app-main-view-toggle>\n\n <!-- Toggle for overlay panel -->\n <app-overlay-view *ngIf=\"uiConfig.showOverlayView\"></app-overlay-view>\n\n <!-- Toggle for selected object panel -->\n <app-object-selection\n *ngIf=\"uiConfig.showObjectSelection\"\n ></app-object-selection>\n\n <!-- Toggle for animating the event data -->\n <app-animate-event *ngIf=\"uiConfig.showAnimateEvent\"></app-animate-event>\n\n <!-- Toggle for animating camera through event -->\n <app-animate-camera\n *ngIf=\"uiConfig.showAnimateCamera\"\n [animationPresets]=\"animationPresets\"\n ></app-animate-camera>\n\n <!-- More information panels -->\n <app-more-info\n [uiConfig]=\"uiConfig\"\n [kinematicsConfig]=\"kinematicsConfig\"\n ></app-more-info>\n\n <!-- Masterclass: tag particles and calculate invariant mass -->\n <app-masterclass-panel\n *ngIf=\"uiConfig?.showMasterclassPanel\"\n [config]=\"masterclassConfig\"\n ></app-masterclass-panel>\n\n <!-- Toggle for performance -->\n <app-performance-toggle\n *ngIf=\"uiConfig.showPerformanceToggle\"\n ></app-performance-toggle>\n\n <!-- Toggle for VR -->\n <app-vr-toggle *ngIf=\"uiConfig.showVRToggle\"></app-vr-toggle>\n\n <!-- Toggle for AR -->\n <app-ar-toggle *ngIf=\"uiConfig.showARToggle\"></app-ar-toggle>\n\n <!-- Make pictures from scene -->\n <app-make-picture *ngIf=\"uiConfig.showMakePicture\"></app-make-picture>\n\n <!-- Toggle for loading geometries modal-->\n <app-io-options\n [eventDataImportOptions]=\"eventDataImportOptions\"\n ></app-io-options>\n\n <!-- Toggle for shareable link constructor modal-->\n <app-share-link *ngIf=\"uiConfig.showShareLink\"></app-share-link>\n\n <!-- Extra options -->\n <ng-content></ng-content>\n</app-ui-menu-wrapper>\n" }]
|
|
4438
|
+
args: [{ standalone: false, selector: 'app-ui-menu', template: "<app-ui-menu-wrapper>\n <!-- Event selector -->\n <app-event-selector></app-event-selector>\n\n <!-- Zoom in and zoom out controls -->\n <app-zoom-controls></app-zoom-controls>\n\n <app-view-options></app-view-options>\n\n <app-auto-rotate></app-auto-rotate>\n\n <!-- Dark theme toggle -->\n <app-dark-theme></app-dark-theme>\n\n <!-- Toggle for clipping geometries -->\n <app-object-clipping\n *ngIf=\"uiConfig.showObjectClipping\"\n ></app-object-clipping>\n\n <!-- Main view toggle -->\n <app-main-view-toggle></app-main-view-toggle>\n\n <!-- Toggle for overlay panel -->\n <app-overlay-view *ngIf=\"uiConfig.showOverlayView\"></app-overlay-view>\n\n <!-- Toggle for selected object panel -->\n <app-object-selection\n *ngIf=\"uiConfig.showObjectSelection\"\n ></app-object-selection>\n\n <!-- Toggle for animating the event data -->\n <app-animate-event *ngIf=\"uiConfig.showAnimateEvent\"></app-animate-event>\n\n <!-- Toggle for animating camera through event -->\n <app-animate-camera\n *ngIf=\"uiConfig.showAnimateCamera\"\n [animationPresets]=\"animationPresets\"\n ></app-animate-camera>\n\n <!-- More information panels -->\n <app-more-info\n [uiConfig]=\"uiConfig\"\n [kinematicsConfig]=\"kinematicsConfig\"\n ></app-more-info>\n\n <!-- Masterclass: tag particles and calculate invariant mass -->\n <app-masterclass-panel\n *ngIf=\"uiConfig?.showMasterclassPanel\"\n [config]=\"masterclassConfig\"\n ></app-masterclass-panel>\n\n <!-- Toggle for performance -->\n <app-performance-toggle\n *ngIf=\"uiConfig.showPerformanceToggle\"\n ></app-performance-toggle>\n\n <!-- Toggle for VR -->\n <app-vr-toggle *ngIf=\"uiConfig.showVRToggle\"></app-vr-toggle>\n\n <!-- Toggle for AR -->\n <app-ar-toggle *ngIf=\"uiConfig.showARToggle\"></app-ar-toggle>\n\n <!-- Make pictures from scene -->\n <app-make-picture *ngIf=\"uiConfig.showMakePicture\"></app-make-picture>\n\n <!-- Toggle for loading geometries modal-->\n <app-io-options\n [eventDataImportOptions]=\"eventDataImportOptions\"\n ></app-io-options>\n\n <!-- Toggle for shareable link constructor modal-->\n <app-share-link *ngIf=\"uiConfig.showShareLink\"></app-share-link>\n\n <!-- Histogram panel -->\n <app-histogram-panel\n *ngIf=\"uiConfig?.showHistogramPanel\"\n [config]=\"histogramConfig\"\n ></app-histogram-panel>\n\n <!-- Extra options -->\n <ng-content></ng-content>\n</app-ui-menu-wrapper>\n" }]
|
|
4355
4439
|
}], null, { eventDataImportOptions: [{
|
|
4356
4440
|
type: Input
|
|
4357
4441
|
}], animationPresets: [{
|
|
4358
4442
|
type: Input
|
|
4443
|
+
}], histogramConfig: [{
|
|
4444
|
+
type: Input
|
|
4359
4445
|
}], uiConfig: [{
|
|
4360
4446
|
type: Input
|
|
4361
4447
|
}], kinematicsConfig: [{
|
|
@@ -4363,9 +4449,9 @@ class UiMenuComponent {
|
|
|
4363
4449
|
}], masterclassConfig: [{
|
|
4364
4450
|
type: Input
|
|
4365
4451
|
}] }); })();
|
|
4366
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UiMenuComponent, { className: "UiMenuComponent", filePath: "components/ui-menu/ui-menu.component.ts", lineNumber:
|
|
4452
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UiMenuComponent, { className: "UiMenuComponent", filePath: "components/ui-menu/ui-menu.component.ts", lineNumber: 61 }); })();
|
|
4367
4453
|
|
|
4368
|
-
const _c0$
|
|
4454
|
+
const _c0$7 = ["qrcodeCanvas"];
|
|
4369
4455
|
class ShareLinkDialogComponent {
|
|
4370
4456
|
dialogRef;
|
|
4371
4457
|
eventDisplay;
|
|
@@ -4455,7 +4541,7 @@ class ShareLinkDialogComponent {
|
|
|
4455
4541
|
}
|
|
4456
4542
|
static ɵfac = function ShareLinkDialogComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ShareLinkDialogComponent)(i0.ɵɵdirectiveInject(i1$1.MatDialogRef), i0.ɵɵdirectiveInject(EventDisplayService)); };
|
|
4457
4543
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ShareLinkDialogComponent, selectors: [["app-share-link-dialog"]], viewQuery: function ShareLinkDialogComponent_Query(rf, ctx) { if (rf & 1) {
|
|
4458
|
-
i0.ɵɵviewQuery(_c0$
|
|
4544
|
+
i0.ɵɵviewQuery(_c0$7, 5);
|
|
4459
4545
|
} if (rf & 2) {
|
|
4460
4546
|
let _t;
|
|
4461
4547
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.qrcodeCanvas = _t.first);
|
|
@@ -4936,7 +5022,7 @@ class EventDataExplorerComponent {
|
|
|
4936
5022
|
}] }); })();
|
|
4937
5023
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EventDataExplorerComponent, { className: "EventDataExplorerComponent", filePath: "components/ui-menu/event-data-explorer/event-data-explorer.component.ts", lineNumber: 15 }); })();
|
|
4938
5024
|
|
|
4939
|
-
const _c0$
|
|
5025
|
+
const _c0$6 = (a0, a1) => ({ "active-icon": a0, "reload-icon": a1 });
|
|
4940
5026
|
class CycleEventsComponent {
|
|
4941
5027
|
eventDisplay;
|
|
4942
5028
|
fileLoader;
|
|
@@ -5027,7 +5113,7 @@ class CycleEventsComponent {
|
|
|
5027
5113
|
i0.ɵɵelementEnd()();
|
|
5028
5114
|
} if (rf & 2) {
|
|
5029
5115
|
i0.ɵɵadvance();
|
|
5030
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(1, _c0$
|
|
5116
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(1, _c0$6, ctx.active, ctx.reloading));
|
|
5031
5117
|
} }, dependencies: [i2.NgClass, i3$1.MatTooltip], styles: ["[_nghost-%COMP%]{display:flex;margin:0 .6rem}[_nghost-%COMP%] .cycle-events[_ngcontent-%COMP%]{display:flex;background:unset;border:none;height:2.5rem;width:2.5rem;min-height:2.5rem;min-width:2.5rem;padding:.65rem;cursor:pointer;align-self:center;transition:all .4s}[_nghost-%COMP%] .cycle-events-icon[_ngcontent-%COMP%]{width:100%;height:100%}[_nghost-%COMP%] .cycle-events-icon.active-icon[_ngcontent-%COMP%]{--phoenix-options-icon-path: #00bcd4}[_nghost-%COMP%] .cycle-events-icon.reload-icon[_ngcontent-%COMP%]{--phoenix-options-icon-path: #77dd77}[_nghost-%COMP%] .cycle-events[_ngcontent-%COMP%]:hover{background-color:var(--phoenix-options-icon-bg);border-radius:40%;transition:all .4s}[_nghost-%COMP%] .cycle-events.disabled[_ngcontent-%COMP%]{cursor:not-allowed;opacity:.4}"] });
|
|
5032
5118
|
}
|
|
5033
5119
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CycleEventsComponent, [{
|
|
@@ -5042,7 +5128,7 @@ class CycleEventsComponent {
|
|
|
5042
5128
|
}] }); })();
|
|
5043
5129
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(CycleEventsComponent, { className: "CycleEventsComponent", filePath: "components/ui-menu/cycle-events/cycle-events.component.ts", lineNumber: 11 }); })();
|
|
5044
5130
|
|
|
5045
|
-
const _c0$
|
|
5131
|
+
const _c0$5 = a0 => ({ "sort-active": a0 });
|
|
5046
5132
|
const _c1$4 = (a0, a1) => ({ "selected-event": a0, "loaded-event": a1 });
|
|
5047
5133
|
const _c2$1 = a0 => ({ "dim-zero": a0 });
|
|
5048
5134
|
function EventBrowserOverlayComponent_div_1_div_1_span_2_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -5195,9 +5281,9 @@ function EventBrowserOverlayComponent_div_1_table_5_th_5_Template(rf, ctx) { if
|
|
|
5195
5281
|
i0.ɵɵadvance(3);
|
|
5196
5282
|
i0.ɵɵtextInterpolate(col_r12);
|
|
5197
5283
|
i0.ɵɵadvance(2);
|
|
5198
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(3, _c0$
|
|
5284
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(3, _c0$5, ctx_r2.isSortActive(col_r12, "desc")));
|
|
5199
5285
|
i0.ɵɵadvance(3);
|
|
5200
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(5, _c0$
|
|
5286
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(5, _c0$5, ctx_r2.isSortActive(col_r12, "asc")));
|
|
5201
5287
|
} }
|
|
5202
5288
|
function EventBrowserOverlayComponent_div_1_table_5_tr_30_div_4_Template(rf, ctx) { if (rf & 1) {
|
|
5203
5289
|
i0.ɵɵelementStart(0, "div", 53);
|
|
@@ -5323,13 +5409,13 @@ function EventBrowserOverlayComponent_div_1_table_5_Template(rf, ctx) { if (rf &
|
|
|
5323
5409
|
i0.ɵɵadvance(5);
|
|
5324
5410
|
i0.ɵɵproperty("ngForOf", ctx_r2.columns);
|
|
5325
5411
|
i0.ɵɵadvance(6);
|
|
5326
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(6, _c0$
|
|
5412
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(6, _c0$5, ctx_r2.isSortActive("_reco", "desc")));
|
|
5327
5413
|
i0.ɵɵadvance(3);
|
|
5328
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(8, _c0$
|
|
5414
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(8, _c0$5, ctx_r2.isSortActive("_reco", "asc")));
|
|
5329
5415
|
i0.ɵɵadvance(8);
|
|
5330
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(10, _c0$
|
|
5416
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(10, _c0$5, ctx_r2.isSortActive("_met", "desc")));
|
|
5331
5417
|
i0.ɵɵadvance(3);
|
|
5332
|
-
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(12, _c0$
|
|
5418
|
+
i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction1(12, _c0$5, ctx_r2.isSortActive("_met", "asc")));
|
|
5333
5419
|
i0.ɵɵadvance(5);
|
|
5334
5420
|
i0.ɵɵproperty("ngForOf", ctx_r2.displayedSummaries);
|
|
5335
5421
|
} }
|
|
@@ -5719,7 +5805,7 @@ class EventBrowserComponent {
|
|
|
5719
5805
|
}], () => [{ type: i1$3.Overlay }], null); })();
|
|
5720
5806
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EventBrowserComponent, { className: "EventBrowserComponent", filePath: "components/ui-menu/event-browser/event-browser.component.ts", lineNumber: 17 }); })();
|
|
5721
5807
|
|
|
5722
|
-
const _c0$
|
|
5808
|
+
const _c0$4 = ["etaPhiCanvas"];
|
|
5723
5809
|
const _c1$3 = ["colorBarCanvas"];
|
|
5724
5810
|
class EtaPhiPanelOverlayComponent {
|
|
5725
5811
|
eventDisplay;
|
|
@@ -6345,7 +6431,7 @@ class EtaPhiPanelOverlayComponent {
|
|
|
6345
6431
|
}
|
|
6346
6432
|
static ɵfac = function EtaPhiPanelOverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EtaPhiPanelOverlayComponent)(i0.ɵɵdirectiveInject(EventDisplayService)); };
|
|
6347
6433
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EtaPhiPanelOverlayComponent, selectors: [["app-eta-phi-panel-overlay"]], viewQuery: function EtaPhiPanelOverlayComponent_Query(rf, ctx) { if (rf & 1) {
|
|
6348
|
-
i0.ɵɵviewQuery(_c0$
|
|
6434
|
+
i0.ɵɵviewQuery(_c0$4, 5);
|
|
6349
6435
|
i0.ɵɵviewQuery(_c1$3, 5);
|
|
6350
6436
|
} if (rf & 2) {
|
|
6351
6437
|
let _t;
|
|
@@ -7023,7 +7109,7 @@ class KinematicsPanelComponent {
|
|
|
7023
7109
|
}] }); })();
|
|
7024
7110
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(KinematicsPanelComponent, { className: "KinematicsPanelComponent", filePath: "components/ui-menu/kinematics-panel/kinematics-panel.component.ts", lineNumber: 22 }); })();
|
|
7025
7111
|
|
|
7026
|
-
const _c0$
|
|
7112
|
+
const _c0$3 = ["infoPanel"];
|
|
7027
7113
|
const _c1$2 = ["eventBrowser"];
|
|
7028
7114
|
const _c2 = ["collectionsInfo"];
|
|
7029
7115
|
const _c3 = ["etaPhiPanel"];
|
|
@@ -7187,7 +7273,7 @@ class MoreInfoComponent {
|
|
|
7187
7273
|
}
|
|
7188
7274
|
static ɵfac = function MoreInfoComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MoreInfoComponent)(); };
|
|
7189
7275
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MoreInfoComponent, selectors: [["app-more-info"]], viewQuery: function MoreInfoComponent_Query(rf, ctx) { if (rf & 1) {
|
|
7190
|
-
i0.ɵɵviewQuery(_c0$
|
|
7276
|
+
i0.ɵɵviewQuery(_c0$3, 5);
|
|
7191
7277
|
i0.ɵɵviewQuery(_c1$2, 5);
|
|
7192
7278
|
i0.ɵɵviewQuery(_c2, 5);
|
|
7193
7279
|
i0.ɵɵviewQuery(_c3, 5);
|
|
@@ -7724,12 +7810,12 @@ function pad(n) {
|
|
|
7724
7810
|
return n < 10 ? `0${n}` : String(n);
|
|
7725
7811
|
}
|
|
7726
7812
|
|
|
7727
|
-
const _c0$
|
|
7813
|
+
const _c0$2 = ["*"];
|
|
7728
7814
|
const _c1$1 = a0 => ({ "ui-menu-hidden": a0 });
|
|
7729
7815
|
class UiMenuWrapperComponent {
|
|
7730
7816
|
hideUIMenu = false;
|
|
7731
7817
|
static ɵfac = function UiMenuWrapperComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UiMenuWrapperComponent)(); };
|
|
7732
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UiMenuWrapperComponent, selectors: [["app-ui-menu-wrapper"]], standalone: false, ngContentSelectors: _c0$
|
|
7818
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: UiMenuWrapperComponent, selectors: [["app-ui-menu-wrapper"]], standalone: false, ngContentSelectors: _c0$2, decls: 7, vars: 5, consts: [["id", "uiMenu"], ["id", "hideUIMenu", "type", "button", "aria-label", "Toggle toolbar visibility", "matTooltipPosition", "above", 3, "click", "matTooltip", "ngClass"], ["href", "assets/icons/expand.svg#expand"], ["id", "optionsPanel", 3, "hidden"]], template: function UiMenuWrapperComponent_Template(rf, ctx) { if (rf & 1) {
|
|
7733
7819
|
i0.ɵɵprojectionDef();
|
|
7734
7820
|
i0.ɵɵelementStart(0, "div", 0)(1, "button", 1);
|
|
7735
7821
|
i0.ɵɵlistener("click", function UiMenuWrapperComponent_Template_button_click_1_listener() { return ctx.hideUIMenu = !ctx.hideUIMenu; });
|
|
@@ -7755,6 +7841,430 @@ class UiMenuWrapperComponent {
|
|
|
7755
7841
|
}], null, null); })();
|
|
7756
7842
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(UiMenuWrapperComponent, { className: "UiMenuWrapperComponent", filePath: "components/ui-menu/ui-menu-wrapper/ui-menu-wrapper.component.ts", lineNumber: 9 }); })();
|
|
7757
7843
|
|
|
7844
|
+
const _c0$1 = ["histogramDiv"];
|
|
7845
|
+
function HistogramPanelOverlayComponent_div_1_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
7846
|
+
i0.ɵɵelementStart(0, "div", 16)(1, "span", 17);
|
|
7847
|
+
i0.ɵɵtext(2);
|
|
7848
|
+
i0.ɵɵelementEnd()();
|
|
7849
|
+
} if (rf & 2) {
|
|
7850
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
7851
|
+
i0.ɵɵadvance(2);
|
|
7852
|
+
i0.ɵɵtextInterpolate(ctx_r1.config.emptyText || "Waiting for data...");
|
|
7853
|
+
} }
|
|
7854
|
+
function HistogramPanelOverlayComponent_div_1_div_5_Template(rf, ctx) { if (rf & 1) {
|
|
7855
|
+
i0.ɵɵelementStart(0, "div", 18)(1, "span", 19);
|
|
7856
|
+
i0.ɵɵtext(2);
|
|
7857
|
+
i0.ɵɵelementEnd()();
|
|
7858
|
+
} if (rf & 2) {
|
|
7859
|
+
const hint_r3 = ctx.$implicit;
|
|
7860
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
7861
|
+
i0.ɵɵstyleProp("left", ctx_r1.getHintPosition(hint_r3.mass), "%")("border-color", hint_r3.color || "#ffffff55");
|
|
7862
|
+
i0.ɵɵadvance();
|
|
7863
|
+
i0.ɵɵstyleProp("color", hint_r3.color || "#ffffff88");
|
|
7864
|
+
i0.ɵɵadvance();
|
|
7865
|
+
i0.ɵɵtextInterpolate(ctx_r1.getHintLabel(hint_r3));
|
|
7866
|
+
} }
|
|
7867
|
+
function HistogramPanelOverlayComponent_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
7868
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
7869
|
+
i0.ɵɵelementStart(0, "div", 3);
|
|
7870
|
+
i0.ɵɵtemplate(1, HistogramPanelOverlayComponent_div_1_div_1_Template, 3, 1, "div", 4);
|
|
7871
|
+
i0.ɵɵelementStart(2, "div", 5);
|
|
7872
|
+
i0.ɵɵelement(3, "div", 6, 0);
|
|
7873
|
+
i0.ɵɵtemplate(5, HistogramPanelOverlayComponent_div_1_div_5_Template, 3, 7, "div", 7);
|
|
7874
|
+
i0.ɵɵelementEnd();
|
|
7875
|
+
i0.ɵɵelementStart(6, "div", 8)(7, "div", 9)(8, "span", 10);
|
|
7876
|
+
i0.ɵɵtext(9, "Entries:");
|
|
7877
|
+
i0.ɵɵelementEnd();
|
|
7878
|
+
i0.ɵɵelementStart(10, "span", 11);
|
|
7879
|
+
i0.ɵɵtext(11);
|
|
7880
|
+
i0.ɵɵelementEnd();
|
|
7881
|
+
i0.ɵɵelementStart(12, "span", 12);
|
|
7882
|
+
i0.ɵɵtext(13, "|");
|
|
7883
|
+
i0.ɵɵelementEnd();
|
|
7884
|
+
i0.ɵɵelementStart(14, "span", 10);
|
|
7885
|
+
i0.ɵɵtext(15, "Mean:");
|
|
7886
|
+
i0.ɵɵelementEnd();
|
|
7887
|
+
i0.ɵɵelementStart(16, "span", 11);
|
|
7888
|
+
i0.ɵɵtext(17);
|
|
7889
|
+
i0.ɵɵpipe(18, "number");
|
|
7890
|
+
i0.ɵɵelementEnd()();
|
|
7891
|
+
i0.ɵɵelementStart(19, "div", 13)(20, "button", 14);
|
|
7892
|
+
i0.ɵɵlistener("click", function HistogramPanelOverlayComponent_div_1_Template_button_click_20_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.resetHistogram()); });
|
|
7893
|
+
i0.ɵɵtext(21, " Reset ");
|
|
7894
|
+
i0.ɵɵelementEnd();
|
|
7895
|
+
i0.ɵɵelementStart(22, "button", 15);
|
|
7896
|
+
i0.ɵɵlistener("click", function HistogramPanelOverlayComponent_div_1_Template_button_click_22_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.exportCSV()); });
|
|
7897
|
+
i0.ɵɵtext(23, " Export ");
|
|
7898
|
+
i0.ɵɵelementEnd()()()();
|
|
7899
|
+
} if (rf & 2) {
|
|
7900
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
7901
|
+
i0.ɵɵadvance();
|
|
7902
|
+
i0.ɵɵproperty("ngIf", ctx_r1.entries === 0);
|
|
7903
|
+
i0.ɵɵadvance(4);
|
|
7904
|
+
i0.ɵɵproperty("ngForOf", ctx_r1.config.hints);
|
|
7905
|
+
i0.ɵɵadvance(6);
|
|
7906
|
+
i0.ɵɵtextInterpolate(ctx_r1.entries);
|
|
7907
|
+
i0.ɵɵadvance(6);
|
|
7908
|
+
i0.ɵɵtextInterpolate(ctx_r1.entries > 0 ? i0.ɵɵpipeBind2(18, 4, ctx_r1.mean, "1.1-1") + " GeV" : "\u2014");
|
|
7909
|
+
} }
|
|
7910
|
+
/** localStorage key prefix for histogram persistence. */
|
|
7911
|
+
const STORAGE_PREFIX = 'phoenix-histogram-';
|
|
7912
|
+
class HistogramPanelOverlayComponent {
|
|
7913
|
+
eventDisplay;
|
|
7914
|
+
/** Whether the histogram panel is visible. Uses setter to trigger draw on show. */
|
|
7915
|
+
_showHistogram = false;
|
|
7916
|
+
set showHistogram(val) {
|
|
7917
|
+
const wasHidden = !this._showHistogram;
|
|
7918
|
+
this._showHistogram = val;
|
|
7919
|
+
if (val && wasHidden) {
|
|
7920
|
+
setTimeout(() => this.drawHistogram(), 0);
|
|
7921
|
+
}
|
|
7922
|
+
else if (!val) {
|
|
7923
|
+
this.drawn = false;
|
|
7924
|
+
}
|
|
7925
|
+
}
|
|
7926
|
+
get showHistogram() {
|
|
7927
|
+
return this._showHistogram;
|
|
7928
|
+
}
|
|
7929
|
+
config = ATLAS_MASS_HISTOGRAM;
|
|
7930
|
+
histogramDiv;
|
|
7931
|
+
entries = 0;
|
|
7932
|
+
mean = 0;
|
|
7933
|
+
sumValues = 0;
|
|
7934
|
+
rawValues = [];
|
|
7935
|
+
histogram;
|
|
7936
|
+
drawn = false;
|
|
7937
|
+
unsubscribe;
|
|
7938
|
+
redrawTimer = null;
|
|
7939
|
+
constructor(eventDisplay) {
|
|
7940
|
+
this.eventDisplay = eventDisplay;
|
|
7941
|
+
}
|
|
7942
|
+
ngOnInit() {
|
|
7943
|
+
const c = this.config;
|
|
7944
|
+
this.histogram = createHistogram('TH1F', c.nbins);
|
|
7945
|
+
this.histogram.fName = 'hmass';
|
|
7946
|
+
this.histogram.fTitle = '';
|
|
7947
|
+
this.histogram.fXaxis.fXmin = c.xmin;
|
|
7948
|
+
this.histogram.fXaxis.fXmax = c.xmax;
|
|
7949
|
+
this.histogram.fXaxis.fTitle = c.xlabel;
|
|
7950
|
+
this.histogram.fYaxis.fTitle = c.ylabel;
|
|
7951
|
+
this.histogram.fLineColor = c.lineColor;
|
|
7952
|
+
this.histogram.fLineWidth = 0;
|
|
7953
|
+
this.histogram.fFillColor = c.fillColor;
|
|
7954
|
+
this.histogram.fFillStyle = c.fillStyle;
|
|
7955
|
+
// Disable stat box — BIT(9) = 512
|
|
7956
|
+
this.histogram.fBits = this.histogram.fBits | 512;
|
|
7957
|
+
// Restore any saved state from a previous session
|
|
7958
|
+
this.restoreFromStorage();
|
|
7959
|
+
const eventName = c.eventName ?? 'result-recorded';
|
|
7960
|
+
this.unsubscribe = this.eventDisplay.on(eventName, (data) => {
|
|
7961
|
+
if (data?.mass != null) {
|
|
7962
|
+
this.addValue(data.mass);
|
|
7963
|
+
}
|
|
7964
|
+
});
|
|
7965
|
+
}
|
|
7966
|
+
ngOnDestroy() {
|
|
7967
|
+
this.unsubscribe?.();
|
|
7968
|
+
if (this.redrawTimer) {
|
|
7969
|
+
clearTimeout(this.redrawTimer);
|
|
7970
|
+
}
|
|
7971
|
+
}
|
|
7972
|
+
/** Save gStyle, apply dark theme values, await callback, then restore gStyle. */
|
|
7973
|
+
async withDarkGStyle(fn) {
|
|
7974
|
+
const saved = {
|
|
7975
|
+
fCanvasColor: gStyle.fCanvasColor,
|
|
7976
|
+
fPadColor: gStyle.fPadColor,
|
|
7977
|
+
fFrameFillColor: gStyle.fFrameFillColor,
|
|
7978
|
+
fFrameLineColor: gStyle.fFrameLineColor,
|
|
7979
|
+
};
|
|
7980
|
+
// Dark theme: 1=black bg, 0=white text/lines
|
|
7981
|
+
gStyle.fCanvasColor = 1;
|
|
7982
|
+
gStyle.fPadColor = 1;
|
|
7983
|
+
gStyle.fFrameFillColor = 1;
|
|
7984
|
+
gStyle.fFrameLineColor = 0;
|
|
7985
|
+
try {
|
|
7986
|
+
return await fn();
|
|
7987
|
+
}
|
|
7988
|
+
finally {
|
|
7989
|
+
gStyle.fCanvasColor = saved.fCanvasColor;
|
|
7990
|
+
gStyle.fPadColor = saved.fPadColor;
|
|
7991
|
+
gStyle.fFrameFillColor = saved.fFrameFillColor;
|
|
7992
|
+
gStyle.fFrameLineColor = saved.fFrameLineColor;
|
|
7993
|
+
}
|
|
7994
|
+
}
|
|
7995
|
+
async drawHistogram() {
|
|
7996
|
+
if (this.histogramDiv?.nativeElement && this.histogram) {
|
|
7997
|
+
// Set axis colors for dark theme directly on histogram object (not gStyle)
|
|
7998
|
+
this.histogram.fXaxis.fAxisColor = 0;
|
|
7999
|
+
this.histogram.fXaxis.fLabelColor = 0;
|
|
8000
|
+
this.histogram.fXaxis.fTitleColor = 0;
|
|
8001
|
+
this.histogram.fYaxis.fAxisColor = 0;
|
|
8002
|
+
this.histogram.fYaxis.fLabelColor = 0;
|
|
8003
|
+
this.histogram.fYaxis.fTitleColor = 0;
|
|
8004
|
+
await this.withDarkGStyle(() => draw(this.histogramDiv.nativeElement, this.histogram, 'hist,no_stat'));
|
|
8005
|
+
this.applyDarkTheme();
|
|
8006
|
+
this.drawn = true;
|
|
8007
|
+
}
|
|
8008
|
+
}
|
|
8009
|
+
/** Apply dark theme to jsroot SVG via direct DOM manipulation. */
|
|
8010
|
+
applyDarkTheme() {
|
|
8011
|
+
const el = this.histogramDiv?.nativeElement;
|
|
8012
|
+
if (!el)
|
|
8013
|
+
return;
|
|
8014
|
+
const svg = el.querySelector('svg');
|
|
8015
|
+
if (svg) {
|
|
8016
|
+
svg.style.background = '#1a1a2e';
|
|
8017
|
+
}
|
|
8018
|
+
el.querySelectorAll('rect').forEach((rect) => {
|
|
8019
|
+
const fill = rect.getAttribute('fill');
|
|
8020
|
+
if (fill === 'white' ||
|
|
8021
|
+
fill === 'rgb(255, 255, 255)' ||
|
|
8022
|
+
fill === '#ffffff' ||
|
|
8023
|
+
fill === 'rgb(255,255,255)') {
|
|
8024
|
+
rect.setAttribute('fill', '#1a1a2e');
|
|
8025
|
+
rect.setAttribute('stroke', 'rgba(255,255,255,0.15)');
|
|
8026
|
+
}
|
|
8027
|
+
});
|
|
8028
|
+
el.querySelectorAll('line').forEach((line) => {
|
|
8029
|
+
const stroke = line.getAttribute('stroke');
|
|
8030
|
+
if (stroke === 'black' ||
|
|
8031
|
+
stroke === 'rgb(0, 0, 0)' ||
|
|
8032
|
+
stroke === '#000000' ||
|
|
8033
|
+
stroke === 'rgb(0,0,0)') {
|
|
8034
|
+
line.setAttribute('stroke', '#aaaaaa');
|
|
8035
|
+
}
|
|
8036
|
+
});
|
|
8037
|
+
el.querySelectorAll('path').forEach((path) => {
|
|
8038
|
+
const stroke = path.getAttribute('stroke');
|
|
8039
|
+
if (stroke === 'black' ||
|
|
8040
|
+
stroke === 'rgb(0, 0, 0)' ||
|
|
8041
|
+
stroke === '#000000' ||
|
|
8042
|
+
stroke === 'rgb(0,0,0)') {
|
|
8043
|
+
path.setAttribute('stroke', '#aaaaaa');
|
|
8044
|
+
}
|
|
8045
|
+
});
|
|
8046
|
+
el.querySelectorAll('text').forEach((text) => {
|
|
8047
|
+
const fill = text.getAttribute('fill');
|
|
8048
|
+
if (fill === 'black' ||
|
|
8049
|
+
fill === 'rgb(0, 0, 0)' ||
|
|
8050
|
+
fill === '#000000' ||
|
|
8051
|
+
fill === 'rgb(0,0,0)' ||
|
|
8052
|
+
!fill) {
|
|
8053
|
+
text.setAttribute('fill', '#cccccc');
|
|
8054
|
+
}
|
|
8055
|
+
});
|
|
8056
|
+
}
|
|
8057
|
+
/** Add a value and schedule a debounced redraw. */
|
|
8058
|
+
addValue(value) {
|
|
8059
|
+
if (!this.histogram)
|
|
8060
|
+
return;
|
|
8061
|
+
this.histogram.Fill(value);
|
|
8062
|
+
this.rawValues.push(value);
|
|
8063
|
+
this.entries++;
|
|
8064
|
+
this.sumValues += value;
|
|
8065
|
+
this.mean = this.sumValues / this.entries;
|
|
8066
|
+
this.saveToStorage();
|
|
8067
|
+
if (this.drawn && this.histogramDiv?.nativeElement) {
|
|
8068
|
+
this.scheduleRedraw();
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
8071
|
+
/** Debounced redraw — coalesces rapid events (e.g. bulk load) into one repaint. */
|
|
8072
|
+
scheduleRedraw() {
|
|
8073
|
+
if (this.redrawTimer)
|
|
8074
|
+
return;
|
|
8075
|
+
this.redrawTimer = setTimeout(async () => {
|
|
8076
|
+
this.redrawTimer = null;
|
|
8077
|
+
if (this.drawn && this.histogramDiv?.nativeElement) {
|
|
8078
|
+
await this.withDarkGStyle(() => redraw(this.histogramDiv.nativeElement, this.histogram, 'hist,no_stat'));
|
|
8079
|
+
this.applyDarkTheme();
|
|
8080
|
+
}
|
|
8081
|
+
}, 50);
|
|
8082
|
+
}
|
|
8083
|
+
/** Reset histogram after user confirmation. */
|
|
8084
|
+
resetHistogram() {
|
|
8085
|
+
if (this.entries === 0)
|
|
8086
|
+
return;
|
|
8087
|
+
if (!confirm(`Clear all ${this.entries} entries? This cannot be undone.`)) {
|
|
8088
|
+
return;
|
|
8089
|
+
}
|
|
8090
|
+
this.clearHistogram();
|
|
8091
|
+
}
|
|
8092
|
+
/** Clear all histogram data and redraw. */
|
|
8093
|
+
async clearHistogram() {
|
|
8094
|
+
if (!this.histogram)
|
|
8095
|
+
return;
|
|
8096
|
+
for (let i = 0; i < this.histogram.fArray.length; i++) {
|
|
8097
|
+
this.histogram.fArray[i] = 0;
|
|
8098
|
+
}
|
|
8099
|
+
this.histogram.fEntries = 0;
|
|
8100
|
+
this.entries = 0;
|
|
8101
|
+
this.mean = 0;
|
|
8102
|
+
this.sumValues = 0;
|
|
8103
|
+
this.rawValues = [];
|
|
8104
|
+
this.clearStorage();
|
|
8105
|
+
if (this.drawn && this.histogramDiv?.nativeElement) {
|
|
8106
|
+
await this.withDarkGStyle(() => redraw(this.histogramDiv.nativeElement, this.histogram, 'hist,no_stat'));
|
|
8107
|
+
this.applyDarkTheme();
|
|
8108
|
+
}
|
|
8109
|
+
}
|
|
8110
|
+
/** Get hint line position as percentage of the wrapper, accounting for jsroot pad margins. */
|
|
8111
|
+
getHintPosition(mass) {
|
|
8112
|
+
const c = this.config;
|
|
8113
|
+
const padLeft = 0.1; // jsroot default pad left margin
|
|
8114
|
+
const padRight = 0.1; // jsroot default pad right margin
|
|
8115
|
+
const fraction = (mass - c.xmin) / (c.xmax - c.xmin);
|
|
8116
|
+
return (padLeft + fraction * (1 - padLeft - padRight)) * 100;
|
|
8117
|
+
}
|
|
8118
|
+
/** Format hint label with mass value and unit for readability. */
|
|
8119
|
+
getHintLabel(hint) {
|
|
8120
|
+
const massStr = hint.mass >= 10
|
|
8121
|
+
? hint.mass.toFixed(1)
|
|
8122
|
+
: hint.mass.toFixed(hint.mass < 1 ? 2 : 1);
|
|
8123
|
+
return `${hint.label} (${massStr} GeV)`;
|
|
8124
|
+
}
|
|
8125
|
+
/** Export histogram data as TSV. */
|
|
8126
|
+
exportCSV() {
|
|
8127
|
+
if (!this.histogram)
|
|
8128
|
+
return;
|
|
8129
|
+
const c = this.config;
|
|
8130
|
+
const binWidth = (c.xmax - c.xmin) / c.nbins;
|
|
8131
|
+
let tsv = 'bin_low\tbin_high\tentries\n';
|
|
8132
|
+
for (let i = 1; i <= c.nbins; i++) {
|
|
8133
|
+
const low = c.xmin + (i - 1) * binWidth;
|
|
8134
|
+
const high = low + binWidth;
|
|
8135
|
+
const content = this.histogram.fArray[i] || 0;
|
|
8136
|
+
tsv += `${low.toFixed(2)}\t${high.toFixed(2)}\t${content}\n`;
|
|
8137
|
+
}
|
|
8138
|
+
const filename = c.title.toLowerCase().replace(/\s+/g, '_') + '_data.tsv';
|
|
8139
|
+
const blob = new Blob([tsv], { type: 'text/tab-separated-values' });
|
|
8140
|
+
const url = URL.createObjectURL(blob);
|
|
8141
|
+
const a = document.createElement('a');
|
|
8142
|
+
a.href = url;
|
|
8143
|
+
a.download = filename;
|
|
8144
|
+
a.click();
|
|
8145
|
+
URL.revokeObjectURL(url);
|
|
8146
|
+
}
|
|
8147
|
+
// --- localStorage persistence ---
|
|
8148
|
+
/** Storage key derived from config title to avoid collisions between configs. */
|
|
8149
|
+
get storageKey() {
|
|
8150
|
+
return (STORAGE_PREFIX + this.config.title.toLowerCase().replace(/\s+/g, '-'));
|
|
8151
|
+
}
|
|
8152
|
+
/** Save raw values to localStorage for crash recovery. */
|
|
8153
|
+
saveToStorage() {
|
|
8154
|
+
try {
|
|
8155
|
+
localStorage.setItem(this.storageKey, JSON.stringify(this.rawValues));
|
|
8156
|
+
}
|
|
8157
|
+
catch {
|
|
8158
|
+
// localStorage full or unavailable — silently ignore
|
|
8159
|
+
}
|
|
8160
|
+
}
|
|
8161
|
+
/** Restore histogram state from localStorage. */
|
|
8162
|
+
restoreFromStorage() {
|
|
8163
|
+
try {
|
|
8164
|
+
const saved = localStorage.getItem(this.storageKey);
|
|
8165
|
+
if (!saved)
|
|
8166
|
+
return;
|
|
8167
|
+
const values = JSON.parse(saved);
|
|
8168
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
8169
|
+
return;
|
|
8170
|
+
for (const v of values) {
|
|
8171
|
+
this.histogram.Fill(v);
|
|
8172
|
+
this.rawValues.push(v);
|
|
8173
|
+
this.entries++;
|
|
8174
|
+
this.sumValues += v;
|
|
8175
|
+
}
|
|
8176
|
+
this.mean = this.sumValues / this.entries;
|
|
8177
|
+
}
|
|
8178
|
+
catch {
|
|
8179
|
+
// Corrupted data — start fresh
|
|
8180
|
+
}
|
|
8181
|
+
}
|
|
8182
|
+
/** Clear saved state from localStorage. */
|
|
8183
|
+
clearStorage() {
|
|
8184
|
+
try {
|
|
8185
|
+
localStorage.removeItem(this.storageKey);
|
|
8186
|
+
}
|
|
8187
|
+
catch {
|
|
8188
|
+
// Ignore
|
|
8189
|
+
}
|
|
8190
|
+
}
|
|
8191
|
+
static ɵfac = function HistogramPanelOverlayComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || HistogramPanelOverlayComponent)(i0.ɵɵdirectiveInject(EventDisplayService)); };
|
|
8192
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: HistogramPanelOverlayComponent, selectors: [["app-histogram-panel-overlay"]], viewQuery: function HistogramPanelOverlayComponent_Query(rf, ctx) { if (rf & 1) {
|
|
8193
|
+
i0.ɵɵviewQuery(_c0$1, 5);
|
|
8194
|
+
} if (rf & 2) {
|
|
8195
|
+
let _t;
|
|
8196
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.histogramDiv = _t.first);
|
|
8197
|
+
} }, inputs: { showHistogram: "showHistogram", config: "config" }, standalone: false, decls: 2, vars: 4, consts: [["histogramDiv", ""], ["icon", "histogram", 3, "overlayTitle", "active", "resizable"], ["class", "histogram-container", 4, "ngIf"], [1, "histogram-container"], ["class", "histogram-empty", 4, "ngIf"], [1, "histogram-wrapper"], [1, "histogram-canvas"], ["class", "hint-line", 3, "left", "borderColor", 4, "ngFor", "ngForOf"], [1, "histogram-footer"], [1, "histogram-stats"], [1, "stat-label"], [1, "stat-value"], [1, "stat-sep"], [1, "histogram-actions"], ["matTooltip", "Clear all entries", 1, "btn-action", 3, "click"], ["matTooltip", "Download bin data as TSV", 1, "btn-action", 3, "click"], [1, "histogram-empty"], [1, "empty-hint"], [1, "hint-line"], [1, "hint-label"]], template: function HistogramPanelOverlayComponent_Template(rf, ctx) { if (rf & 1) {
|
|
8198
|
+
i0.ɵɵelementStart(0, "app-overlay", 1);
|
|
8199
|
+
i0.ɵɵtemplate(1, HistogramPanelOverlayComponent_div_1_Template, 24, 7, "div", 2);
|
|
8200
|
+
i0.ɵɵelementEnd();
|
|
8201
|
+
} if (rf & 2) {
|
|
8202
|
+
i0.ɵɵproperty("overlayTitle", ctx.config.title)("active", ctx.showHistogram)("resizable", false);
|
|
8203
|
+
i0.ɵɵadvance();
|
|
8204
|
+
i0.ɵɵproperty("ngIf", ctx.showHistogram);
|
|
8205
|
+
} }, dependencies: [i2.NgForOf, i2.NgIf, i3$1.MatTooltip, OverlayComponent, i2.DecimalPipe], styles: [".histogram-container[_ngcontent-%COMP%]{padding:.5rem;width:450px;display:flex;flex-direction:column;gap:.4rem}.histogram-wrapper[_ngcontent-%COMP%]{position:relative;min-height:280px;border-radius:6px;overflow:hidden;background:#1a1a2e}.histogram-canvas[_ngcontent-%COMP%]{width:100%;height:280px;border-radius:6px;overflow:hidden}.histogram-canvas[_ngcontent-%COMP%] svg{background:#1a1a2e!important}.hint-line[_ngcontent-%COMP%]{position:absolute;top:10%;bottom:10%;border-left:1.5px dashed;opacity:.8;pointer-events:none;z-index:10}.hint-label[_ngcontent-%COMP%]{position:absolute;top:-2px;left:4px;font-size:.75rem;font-weight:600;letter-spacing:.02em;white-space:nowrap;opacity:.95;text-shadow:0 1px 3px rgba(0,0,0,.6)}.histogram-empty[_ngcontent-%COMP%]{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;z-index:5;pointer-events:none}.histogram-empty[_ngcontent-%COMP%] .empty-hint[_ngcontent-%COMP%]{font-size:.75rem;color:var(--phoenix-text-color-secondary);opacity:.5;text-align:center;max-width:250px;line-height:1.4}.histogram-footer[_ngcontent-%COMP%]{display:flex;justify-content:space-between;align-items:center;padding:.3rem .2rem 0}.histogram-stats[_ngcontent-%COMP%]{display:flex;align-items:baseline;gap:.35rem}.histogram-stats[_ngcontent-%COMP%] .stat-label[_ngcontent-%COMP%]{font-size:.7rem;color:var(--phoenix-text-color-secondary);opacity:.6}.histogram-stats[_ngcontent-%COMP%] .stat-value[_ngcontent-%COMP%]{font-size:.8rem;color:var(--phoenix-text-color);font-weight:500}.histogram-stats[_ngcontent-%COMP%] .stat-sep[_ngcontent-%COMP%]{font-size:.7rem;color:var(--phoenix-text-color-secondary);opacity:.3;margin:0 .1rem}.histogram-actions[_ngcontent-%COMP%]{display:flex;gap:.3rem}.btn-action[_ngcontent-%COMP%]{font-size:.7rem;padding:.2rem .5rem;border:1px solid rgba(255,255,255,.08);border-radius:5px;background:#ffffff0a;color:var(--phoenix-text-color-secondary);cursor:pointer;transition:all .15s}.btn-action[_ngcontent-%COMP%]:hover{background:#ffffff1a;border-color:#ffffff26}"] });
|
|
8206
|
+
}
|
|
8207
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(HistogramPanelOverlayComponent, [{
|
|
8208
|
+
type: Component,
|
|
8209
|
+
args: [{ standalone: false, selector: 'app-histogram-panel-overlay', template: "<app-overlay\n [overlayTitle]=\"config.title\"\n icon=\"histogram\"\n [active]=\"showHistogram\"\n [resizable]=\"false\"\n>\n <div class=\"histogram-container\" *ngIf=\"showHistogram\">\n <!-- Empty state guidance -->\n <div class=\"histogram-empty\" *ngIf=\"entries === 0\">\n <span class=\"empty-hint\">{{\n config.emptyText || 'Waiting for data...'\n }}</span>\n </div>\n\n <!-- Histogram canvas with hint overlays -->\n <div class=\"histogram-wrapper\">\n <div #histogramDiv class=\"histogram-canvas\"></div>\n\n <!-- Reference lines for known resonances -->\n <div\n class=\"hint-line\"\n *ngFor=\"let hint of config.hints\"\n [style.left.%]=\"getHintPosition(hint.mass)\"\n [style.borderColor]=\"hint.color || '#ffffff55'\"\n >\n <span class=\"hint-label\" [style.color]=\"hint.color || '#ffffff88'\">{{\n getHintLabel(hint)\n }}</span>\n </div>\n </div>\n\n <!-- Footer: stats + actions -->\n <div class=\"histogram-footer\">\n <div class=\"histogram-stats\">\n <span class=\"stat-label\">Entries:</span>\n <span class=\"stat-value\">{{ entries }}</span>\n <span class=\"stat-sep\">|</span>\n <span class=\"stat-label\">Mean:</span>\n <span class=\"stat-value\">{{\n entries > 0 ? (mean | number: '1.1-1') + ' GeV' : '\u2014'\n }}</span>\n </div>\n <div class=\"histogram-actions\">\n <button\n class=\"btn-action\"\n (click)=\"resetHistogram()\"\n matTooltip=\"Clear all entries\"\n >\n Reset\n </button>\n <button\n class=\"btn-action\"\n (click)=\"exportCSV()\"\n matTooltip=\"Download bin data as TSV\"\n >\n Export\n </button>\n </div>\n </div>\n </div>\n</app-overlay>\n", styles: [".histogram-container{padding:.5rem;width:450px;display:flex;flex-direction:column;gap:.4rem}.histogram-wrapper{position:relative;min-height:280px;border-radius:6px;overflow:hidden;background:#1a1a2e}.histogram-canvas{width:100%;height:280px;border-radius:6px;overflow:hidden}.histogram-canvas ::ng-deep svg{background:#1a1a2e!important}.hint-line{position:absolute;top:10%;bottom:10%;border-left:1.5px dashed;opacity:.8;pointer-events:none;z-index:10}.hint-label{position:absolute;top:-2px;left:4px;font-size:.75rem;font-weight:600;letter-spacing:.02em;white-space:nowrap;opacity:.95;text-shadow:0 1px 3px rgba(0,0,0,.6)}.histogram-empty{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;z-index:5;pointer-events:none}.histogram-empty .empty-hint{font-size:.75rem;color:var(--phoenix-text-color-secondary);opacity:.5;text-align:center;max-width:250px;line-height:1.4}.histogram-footer{display:flex;justify-content:space-between;align-items:center;padding:.3rem .2rem 0}.histogram-stats{display:flex;align-items:baseline;gap:.35rem}.histogram-stats .stat-label{font-size:.7rem;color:var(--phoenix-text-color-secondary);opacity:.6}.histogram-stats .stat-value{font-size:.8rem;color:var(--phoenix-text-color);font-weight:500}.histogram-stats .stat-sep{font-size:.7rem;color:var(--phoenix-text-color-secondary);opacity:.3;margin:0 .1rem}.histogram-actions{display:flex;gap:.3rem}.btn-action{font-size:.7rem;padding:.2rem .5rem;border:1px solid rgba(255,255,255,.08);border-radius:5px;background:#ffffff0a;color:var(--phoenix-text-color-secondary);cursor:pointer;transition:all .15s}.btn-action:hover{background:#ffffff1a;border-color:#ffffff26}\n"] }]
|
|
8210
|
+
}], () => [{ type: EventDisplayService }], { showHistogram: [{
|
|
8211
|
+
type: Input
|
|
8212
|
+
}], config: [{
|
|
8213
|
+
type: Input
|
|
8214
|
+
}], histogramDiv: [{
|
|
8215
|
+
type: ViewChild,
|
|
8216
|
+
args: ['histogramDiv']
|
|
8217
|
+
}] }); })();
|
|
8218
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HistogramPanelOverlayComponent, { className: "HistogramPanelOverlayComponent", filePath: "components/ui-menu/histogram-panel/histogram-panel-overlay/histogram-panel-overlay.component.ts", lineNumber: 26 }); })();
|
|
8219
|
+
|
|
8220
|
+
class HistogramPanelComponent {
|
|
8221
|
+
overlay;
|
|
8222
|
+
showHistogram = false;
|
|
8223
|
+
overlayWindow;
|
|
8224
|
+
config;
|
|
8225
|
+
constructor(overlay) {
|
|
8226
|
+
this.overlay = overlay;
|
|
8227
|
+
}
|
|
8228
|
+
ngOnInit() {
|
|
8229
|
+
const overlayRef = this.overlay.create();
|
|
8230
|
+
const overlayPortal = new ComponentPortal(HistogramPanelOverlayComponent);
|
|
8231
|
+
this.overlayWindow = overlayRef.attach(overlayPortal);
|
|
8232
|
+
this.overlayWindow.instance.showHistogram = this.showHistogram;
|
|
8233
|
+
if (this.config) {
|
|
8234
|
+
this.overlayWindow.instance.config = this.config;
|
|
8235
|
+
}
|
|
8236
|
+
}
|
|
8237
|
+
ngOnChanges(changes) {
|
|
8238
|
+
if (changes['config'] && this.overlayWindow) {
|
|
8239
|
+
if (this.config) {
|
|
8240
|
+
this.overlayWindow.instance.config = this.config;
|
|
8241
|
+
}
|
|
8242
|
+
}
|
|
8243
|
+
}
|
|
8244
|
+
ngOnDestroy() {
|
|
8245
|
+
this.overlayWindow.destroy();
|
|
8246
|
+
}
|
|
8247
|
+
toggleOverlay() {
|
|
8248
|
+
this.showHistogram = !this.showHistogram;
|
|
8249
|
+
this.overlayWindow.instance.showHistogram = this.showHistogram;
|
|
8250
|
+
}
|
|
8251
|
+
static ɵfac = function HistogramPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || HistogramPanelComponent)(i0.ɵɵdirectiveInject(i1$3.Overlay)); };
|
|
8252
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: HistogramPanelComponent, selectors: [["app-histogram-panel"]], inputs: { config: "config" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 1, vars: 1, consts: [["tooltip", "Histogram panel", "icon", "histogram", 3, "click", "active"]], template: function HistogramPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
8253
|
+
i0.ɵɵelementStart(0, "app-menu-toggle", 0);
|
|
8254
|
+
i0.ɵɵlistener("click", function HistogramPanelComponent_Template_app_menu_toggle_click_0_listener() { return ctx.toggleOverlay(); });
|
|
8255
|
+
i0.ɵɵelementEnd();
|
|
8256
|
+
} if (rf & 2) {
|
|
8257
|
+
i0.ɵɵproperty("active", ctx.showHistogram);
|
|
8258
|
+
} }, dependencies: [MenuToggleComponent], encapsulation: 2 });
|
|
8259
|
+
}
|
|
8260
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(HistogramPanelComponent, [{
|
|
8261
|
+
type: Component,
|
|
8262
|
+
args: [{ standalone: false, selector: 'app-histogram-panel', template: "<app-menu-toggle\n tooltip=\"Histogram panel\"\n icon=\"histogram\"\n [active]=\"showHistogram\"\n (click)=\"toggleOverlay()\"\n>\n</app-menu-toggle>\n" }]
|
|
8263
|
+
}], () => [{ type: i1$3.Overlay }], { config: [{
|
|
8264
|
+
type: Input
|
|
8265
|
+
}] }); })();
|
|
8266
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(HistogramPanelComponent, { className: "HistogramPanelComponent", filePath: "components/ui-menu/histogram-panel/histogram-panel.component.ts", lineNumber: 21 }); })();
|
|
8267
|
+
|
|
7758
8268
|
function MasterclassPanelOverlayComponent_div_1_option_8_Template(rf, ctx) { if (rf & 1) {
|
|
7759
8269
|
i0.ɵɵelementStart(0, "option", 14);
|
|
7760
8270
|
i0.ɵɵtext(1);
|
|
@@ -8598,6 +9108,8 @@ const PHOENIX_COMPONENTS = [
|
|
|
8598
9108
|
FileExplorerComponent,
|
|
8599
9109
|
RingLoaderComponent,
|
|
8600
9110
|
CycleEventsComponent,
|
|
9111
|
+
HistogramPanelComponent,
|
|
9112
|
+
HistogramPanelOverlayComponent,
|
|
8601
9113
|
EventBrowserComponent,
|
|
8602
9114
|
EventBrowserOverlayComponent,
|
|
8603
9115
|
EtaPhiPanelComponent,
|
|
@@ -8732,6 +9244,8 @@ class PhoenixUIModule {
|
|
|
8732
9244
|
FileExplorerComponent,
|
|
8733
9245
|
RingLoaderComponent,
|
|
8734
9246
|
CycleEventsComponent,
|
|
9247
|
+
HistogramPanelComponent,
|
|
9248
|
+
HistogramPanelOverlayComponent,
|
|
8735
9249
|
EventBrowserComponent,
|
|
8736
9250
|
EventBrowserOverlayComponent,
|
|
8737
9251
|
EtaPhiPanelComponent,
|
|
@@ -8811,6 +9325,8 @@ class PhoenixUIModule {
|
|
|
8811
9325
|
FileExplorerComponent,
|
|
8812
9326
|
RingLoaderComponent,
|
|
8813
9327
|
CycleEventsComponent,
|
|
9328
|
+
HistogramPanelComponent,
|
|
9329
|
+
HistogramPanelOverlayComponent,
|
|
8814
9330
|
EventBrowserComponent,
|
|
8815
9331
|
EventBrowserOverlayComponent,
|
|
8816
9332
|
EtaPhiPanelComponent,
|
|
@@ -8840,6 +9356,7 @@ i0.ɵɵsetComponentScope(UiMenuComponent, [i2.NgIf, UiMenuWrapperComponent,
|
|
|
8840
9356
|
MakePictureComponent,
|
|
8841
9357
|
PerformanceToggleComponent,
|
|
8842
9358
|
ShareLinkComponent,
|
|
9359
|
+
HistogramPanelComponent,
|
|
8843
9360
|
MasterclassPanelComponent], []);
|
|
8844
9361
|
|
|
8845
9362
|
// Components
|
|
@@ -8848,5 +9365,5 @@ i0.ɵɵsetComponentScope(UiMenuComponent, [i2.NgIf, UiMenuWrapperComponent,
|
|
|
8848
9365
|
* Generated bundle index. Do not edit.
|
|
8849
9366
|
*/
|
|
8850
9367
|
|
|
8851
|
-
export { AnimateCameraComponent, AnimateEventComponent, ArToggleComponent, AttributePipe, AutoRotateComponent, CartesianGridConfigComponent, CollectionsInfoComponent, CollectionsInfoOverlayComponent, ConfigSliderComponent, CycleEventsComponent, DarkThemeComponent, DownloadAnimationDialogComponent, EmbedMenuComponent, EtaPhiPanelComponent, EtaPhiPanelOverlayComponent, EventBrowserComponent, EventBrowserOverlayComponent, EventDataExplorerComponent, EventDataExplorerDialogComponent, EventDataFormat, EventDisplayService, EventSelectorComponent, ExperimentInfoComponent, ExperimentLinkComponent, FileEvent, FileExplorerComponent, FileNode, GeometryBrowserComponent, GeometryBrowserOverlayComponent, IOOptionsDialogComponent, ImportOption, InfoPanelComponent, InfoPanelOverlayComponent, IoOptionsComponent, KinematicsPanelComponent, KinematicsPanelOverlayComponent, LoaderComponent, MainViewToggleComponent, MakePictureComponent, MasterclassPanelComponent, MasterclassPanelOverlayComponent, MenuToggleComponent, MoreInfoComponent, NavComponent, NotificationService, NotificationToastComponent, ObjectClippingComponent, ObjectSelectionComponent, ObjectSelectionOverlayComponent, OverlayCascadeService, OverlayComponent, OverlayViewComponent, OverlayViewWindowComponent, PerformanceToggleComponent, PhoenixMenuComponent, PhoenixMenuItemComponent, PhoenixUIModule, RingLoaderComponent, SSModeComponent, SessionPillComponent, ShareLinkComponent, ShareLinkDialogComponent, ShortcutsDialogComponent, TreeMenuComponent, TreeMenuItemComponent, UiMenuComponent, UiMenuWrapperComponent, ViewOptionsComponent, VrToggleComponent, ZoomControlsComponent, defaultAnimationPresets, defaultUIMenuConfig };
|
|
9368
|
+
export { AnimateCameraComponent, AnimateEventComponent, ArToggleComponent, AttributePipe, AutoRotateComponent, CartesianGridConfigComponent, CollectionsInfoComponent, CollectionsInfoOverlayComponent, ConfigSliderComponent, CycleEventsComponent, DarkThemeComponent, DownloadAnimationDialogComponent, EmbedMenuComponent, EtaPhiPanelComponent, EtaPhiPanelOverlayComponent, EventBrowserComponent, EventBrowserOverlayComponent, EventDataExplorerComponent, EventDataExplorerDialogComponent, EventDataFormat, EventDisplayService, EventSelectorComponent, ExperimentInfoComponent, ExperimentLinkComponent, FileEvent, FileExplorerComponent, FileNode, GeometryBrowserComponent, GeometryBrowserOverlayComponent, HistogramPanelComponent, HistogramPanelOverlayComponent, IOOptionsDialogComponent, ImportOption, InfoPanelComponent, InfoPanelOverlayComponent, IoOptionsComponent, KinematicsPanelComponent, KinematicsPanelOverlayComponent, LoaderComponent, MainViewToggleComponent, MakePictureComponent, MasterclassPanelComponent, MasterclassPanelOverlayComponent, MenuToggleComponent, MoreInfoComponent, NavComponent, NotificationService, NotificationToastComponent, ObjectClippingComponent, ObjectSelectionComponent, ObjectSelectionOverlayComponent, OverlayCascadeService, OverlayComponent, OverlayViewComponent, OverlayViewWindowComponent, PerformanceToggleComponent, PhoenixMenuComponent, PhoenixMenuItemComponent, PhoenixUIModule, RingLoaderComponent, SSModeComponent, SessionPillComponent, ShareLinkComponent, ShareLinkDialogComponent, ShortcutsDialogComponent, TreeMenuComponent, TreeMenuItemComponent, UiMenuComponent, UiMenuWrapperComponent, ViewOptionsComponent, VrToggleComponent, ZoomControlsComponent, defaultAnimationPresets, defaultUIMenuConfig };
|
|
8852
9369
|
//# sourceMappingURL=phoenix-ui-components.mjs.map
|