@rocketshow/designer 1.64.0 → 1.67.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, HostListener, ViewChild, Component, Pipe, EventEmitter, Output, Input, Directive, ChangeDetectionStrategy, ViewEncapsulation, NgModule } from '@angular/core';
2
+ import { Injectable, HostListener, ViewChild, Component, Pipe, EventEmitter, Output, Input, Directive, ChangeDetectionStrategy, ViewEncapsulation, ContentChild, NgModule } from '@angular/core';
3
3
  import * as i2 from '@ngx-translate/core';
4
4
  import { TranslateModule } from '@ngx-translate/core';
5
5
  import * as i1$1 from 'ngx-bootstrap/modal';
@@ -34,7 +34,6 @@ import { NgxBootstrapSliderModule } from 'ngx-bootstrap-slider';
34
34
  import * as i10$1 from '@angular/common';
35
35
  import * as i6 from 'ngx-bootstrap/accordion';
36
36
  import { AccordionModule } from 'ngx-bootstrap/accordion';
37
- import { KEYS, TREE_ACTIONS, TreeModule } from '@ali-hm/angular-tree-component';
38
37
  import { BrowserModule } from '@angular/platform-browser';
39
38
  import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
40
39
 
@@ -2207,6 +2206,7 @@ class PresetService {
2207
2206
  for (let i = this.selectedPreset.fixtures.length - 1; i >= 0; i--) {
2208
2207
  const projectFixture = this.fixtureService.getFixtureByUuid(this.selectedPreset.fixtures[i].fixtureUuid);
2209
2208
  if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
2209
+ projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid &&
2210
2210
  ((!this.selectedPreset.fixtures[i].pixelKey && !pixelKey) || this.selectedPreset.fixtures[i].pixelKey === pixelKey)) {
2211
2211
  this.selectedPreset.fixtures.splice(i, 1);
2212
2212
  }
@@ -2216,7 +2216,7 @@ class PresetService {
2216
2216
  for (const projectPresetFixture of this.projectService.project.presetFixtures) {
2217
2217
  if ((!projectPresetFixture.pixelKey && !pixelKey) || projectPresetFixture.pixelKey === pixelKey) {
2218
2218
  const projectFixture = this.fixtureService.getFixtureByUuid(projectPresetFixture.fixtureUuid);
2219
- if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
2219
+ if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel && projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid) {
2220
2220
  const presetFixture = new PresetFixture();
2221
2221
  presetFixture.fixtureUuid = projectPresetFixture.fixtureUuid;
2222
2222
  presetFixture.pixelKey = pixelKey;
@@ -2286,6 +2286,7 @@ class PresetService {
2286
2286
  const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
2287
2287
  for (const projectFixture of this.projectService.project.fixtures) {
2288
2288
  if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
2289
+ projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid &&
2289
2290
  !this.fixtureIsSelected(projectFixture, presetFixture.pixelKey, preset)) {
2290
2291
  const newPresetFixture = new PresetFixture();
2291
2292
  newPresetFixture.fixtureUuid = projectFixture.uuid;
@@ -5197,7 +5198,7 @@ class FixturePoolCreateFromFileComponent {
5197
5198
  // validate the file
5198
5199
  const text = event.target.result;
5199
5200
  const json = JSON.parse(text);
5200
- if (json['$schema'].match('https://raw.githubusercontent.com/OpenLightingProject/open-fixture-library/schema-(.*)/schemas/fixture.json')) {
5201
+ if (json['$schema'].match(/open-fixture-library\/(?:schema-(.*?)|master)\/schemas\/fixture\.json/)) {
5201
5202
  // create the metadata from the file. we don't have the corresponding
5202
5203
  // manufacturer-file, therefore we just assume the attributes from the
5203
5204
  // fixture-file.
@@ -5416,11 +5417,11 @@ class FixturePoolEditUniversesComponent {
5416
5417
  this.bsModalRef.hide();
5417
5418
  }
5418
5419
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolEditUniversesComponent, deps: [{ token: i1$1.BsModalRef }, { token: UuidService }], target: i0.ɵɵFactoryTarget.Component }); }
5419
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolEditUniversesComponent, isStandalone: false, selector: "lib-fixture-pool-edit-universes", ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse()\"\n >\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
5420
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolEditUniversesComponent, isStandalone: false, selector: "lib-fixture-pool-edit-universes", ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" [disabled]=\"!newUniverseName || !newUniverseName.trim()\" (click)=\"addUniverse()\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
5420
5421
  }
5421
5422
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolEditUniversesComponent, decorators: [{
5422
5423
  type: Component,
5423
- args: [{ selector: 'lib-fixture-pool-edit-universes', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse()\"\n >\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
5424
+ args: [{ selector: 'lib-fixture-pool-edit-universes', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" [disabled]=\"!newUniverseName || !newUniverseName.trim()\" (click)=\"addUniverse()\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
5424
5425
  }], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: UuidService }] });
5425
5426
 
5426
5427
  class FixturePoolComponent {
@@ -5614,9 +5615,11 @@ class FixturePoolComponent {
5614
5615
  const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
5615
5616
  if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
5616
5617
  if (occupiedFixture) {
5617
- if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel || occupiedFixture.modeShortName !== fixture.modeShortName) {
5618
- // fixtures are allowed to overlap, if they start at the same channel and
5619
- // use the same mode. otherwise it's not allowed.
5618
+ if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel ||
5619
+ occupiedFixture.modeShortName !== fixture.modeShortName ||
5620
+ occupiedFixture.dmxUniverseUuid !== fixture.dmxUniverseUuid) {
5621
+ // fixtures are allowed to overlap, if they start at the same channel,
5622
+ // use the same mode and belong to the same universe. otherwise it's not allowed.
5620
5623
  return true;
5621
5624
  }
5622
5625
  }
@@ -5845,11 +5848,11 @@ class FixturePoolComponent {
5845
5848
  this.ok();
5846
5849
  }
5847
5850
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolComponent, deps: [{ token: i1$1.BsModalRef }, { token: FixtureService }, { token: UuidService }, { token: ProjectService }, { token: PreviewService }, { token: i2.TranslateService }, { token: i3$1.ToastrService }, { token: PresetService }, { token: ConfigService }, { token: i1$1.BsModalService }, { token: LivePreviewService }], target: i0.ɵɵFactoryTarget.Component }); }
5848
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolComponent, isStandalone: false, selector: "lib-app-fixture-pool", host: { listeners: { "window:mouseup": "mouseUp($event)", "document:keydown.enter": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ArraySortPipe, name: "sort" }] }); }
5851
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolComponent, isStandalone: false, selector: "lib-app-fixture-pool", host: { listeners: { "window:mouseup": "mouseUp($event)", "document:keydown.enter": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedFixture.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture.dmxUniverseUuid = $event\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ArraySortPipe, name: "sort" }] }); }
5849
5852
  }
5850
5853
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolComponent, decorators: [{
5851
5854
  type: Component,
5852
- args: [{ selector: 'lib-app-fixture-pool', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
5855
+ args: [{ selector: 'lib-app-fixture-pool', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">&times;</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\">&nbsp;</small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedFixture.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture.dmxUniverseUuid = $event\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
5853
5856
  }], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: FixtureService }, { type: UuidService }, { type: ProjectService }, { type: PreviewService }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: PresetService }, { type: ConfigService }, { type: i1$1.BsModalService }, { type: LivePreviewService }], propDecorators: { mouseUp: [{
5854
5857
  type: HostListener,
5855
5858
  args: ['window:mouseup', ['$event']]
@@ -7947,64 +7950,6 @@ class PresetComponent {
7947
7950
  this.projectService = projectService;
7948
7951
  this.introService = introService;
7949
7952
  this.modalService = modalService;
7950
- let actionMapping = {
7951
- mouse: {
7952
- click: (tree, node, $event) => {
7953
- // block activation for folders (or any condition you want)
7954
- if (node.data.isFolder) {
7955
- // optional: make click expand/collapse instead
7956
- TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
7957
- return;
7958
- }
7959
- TREE_ACTIONS.ACTIVATE(tree, node, $event);
7960
- },
7961
- },
7962
- keys: {
7963
- [KEYS.ENTER]: (tree, node, $event) => {
7964
- if (!node.data.isFolder)
7965
- TREE_ACTIONS.ACTIVATE(tree, node, $event);
7966
- },
7967
- [KEYS.SPACE]: (tree, node, $event) => {
7968
- if (!node.data.isFolder)
7969
- TREE_ACTIONS.ACTIVATE(tree, node, $event);
7970
- },
7971
- },
7972
- };
7973
- this.treeOptions = {
7974
- displayField: 'name',
7975
- isExpandedField: 'expanded',
7976
- idField: 'uuid',
7977
- hasChildrenField: 'nodes',
7978
- // actionMapping: {
7979
- // mouse: {
7980
- // dblClick: (tree, node, $event) => {
7981
- // if (node.hasChildren) TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
7982
- // }
7983
- // },
7984
- // keys: {
7985
- // [KEYS.ENTER]: (tree, node, $event) => {
7986
- // node.expandAll();
7987
- // }
7988
- // }
7989
- // },
7990
- actionMapping: actionMapping,
7991
- nodeHeight: 23,
7992
- allowDrag: (node) => {
7993
- return true;
7994
- },
7995
- allowDrop: (node, target) => {
7996
- // only allow dropping into folders or to the root level
7997
- return !target.parent.data.id || target.parent.data.isFolder;
7998
- },
7999
- allowDragoverStyling: true,
8000
- levelPadding: 10,
8001
- useVirtualScroll: true,
8002
- animateExpand: true,
8003
- scrollOnActivate: true,
8004
- animateSpeed: 10,
8005
- animateAcceleration: 1.2,
8006
- scrollContainer: document.documentElement,
8007
- };
8008
7953
  this.treeNodes = [
8009
7954
  {
8010
7955
  id: 1,
@@ -8017,7 +7962,7 @@ class PresetComponent {
8017
7962
  },
8018
7963
  {
8019
7964
  id: 4,
8020
- name: 'root1',
7965
+ name: 'root2',
8021
7966
  isFolder: true,
8022
7967
  children: [
8023
7968
  { id: 5, name: 'child1', isFolder: false },
@@ -8027,8 +7972,8 @@ class PresetComponent {
8027
7972
  ];
8028
7973
  }
8029
7974
  ngOnInit() { }
8030
- onActivate(event) {
8031
- console.log(event);
7975
+ onActivate(node) {
7976
+ console.log(node);
8032
7977
  }
8033
7978
  selectPreset(index) {
8034
7979
  this.projectService.project.previewPreset = true;
@@ -8077,15 +8022,12 @@ class PresetComponent {
8077
8022
  });
8078
8023
  }
8079
8024
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PresetComponent, deps: [{ token: PresetService }, { token: SceneService }, { token: ProjectService }, { token: IntroService }, { token: i1$1.BsModalService }], target: i0.ɵɵFactoryTarget.Component }); }
8080
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PresetComponent, isStandalone: false, selector: "lib-app-preset", viewQueries: [{ propertyName: "tree", first: true, predicate: ["tree"], descendants: true }], ngImport: i0, template: "<div\n class=\"card border-secondary h-100 panel card-intro-preset card-intro-active\"\n [class.card-intro-active]=\"introService.showStep('presets')\"\n>\n <div class=\"card-header d-flex\">\n <div>\n {{ 'designer.preset.title' | translate }}\n </div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"removePreset(); (false)\"\n ><i class=\"fa fa-minus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"addPreset(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of presets -->\n <!-- <tree-root #tree [nodes]=\"treeNodes\" [options]=\"treeOptions\" (activate)=\"onActivate($event)\">\n <ng-template #treeNodeTemplate let-node let-index=\"index\">\n <span>{{ node.data.name }}</span>\n </ng-template>\n </tree-root> -->\n\n <div class=\"list-group\" [sortablejs]=\"projectService.project.presets\">\n @for (item of projectService.project.presets; track item; let i = $index) {\n <div\n class=\"list-group-item\"\n (click)=\"selectPreset(i)\"\n [class.active-light]=\"!projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.active]=\"projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.inactive-list-item]=\"!sceneService.presetIsSelected(item)\"\n >\n <div class=\"row d-flex\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n [disabled]=\"!enableCheckbox()\"\n class=\"form-check-input\"\n id=\"active\"\n [ngModel]=\"sceneService.presetIsSelected(item)\"\n (ngModelChange)=\"activatePreset($event, i)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n <div>\n {{ item.name }}\n </div>\n <div class=\"my-auto ml-auto mr-2 d-flex\">\n <button type=\"button\" class=\"btn btn-secondary btn-sm py-0 px-1\" (click)=\"openSettings(item); (false)\">...</button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i3$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
8025
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: PresetComponent, isStandalone: false, selector: "lib-app-preset", ngImport: i0, template: "<div\n class=\"card border-secondary h-100 panel card-intro-preset card-intro-active\"\n [class.card-intro-active]=\"introService.showStep('presets')\"\n>\n <div class=\"card-header d-flex\">\n <div>\n {{ 'designer.preset.title' | translate }}\n </div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"removePreset(); (false)\"\n ><i class=\"fa fa-minus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"addPreset(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of presets -->\n <!-- <lib-tree [nodes]=\"treeNodes\" (activate)=\"onActivate($event)\">\n <ng-template #nodeTemplate let-node>\n <span>{{ node.name }}</span>\n </ng-template>\n </lib-tree> -->\n\n <div class=\"list-group\" [sortablejs]=\"projectService.project.presets\">\n @for (item of projectService.project.presets; track item; let i = $index) {\n <div\n class=\"list-group-item\"\n (click)=\"selectPreset(i)\"\n [class.active-light]=\"!projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.active]=\"projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.inactive-list-item]=\"!sceneService.presetIsSelected(item)\"\n >\n <div class=\"row d-flex\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n [disabled]=\"!enableCheckbox()\"\n class=\"form-check-input\"\n id=\"active\"\n [ngModel]=\"sceneService.presetIsSelected(item)\"\n (ngModelChange)=\"activatePreset($event, i)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n <div>\n {{ item.name }}\n </div>\n <div class=\"my-auto ml-auto mr-2 d-flex\">\n <button type=\"button\" class=\"btn btn-secondary btn-sm py-0 px-1\" (click)=\"openSettings(item); (false)\">...</button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i3$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
8081
8026
  }
8082
8027
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PresetComponent, decorators: [{
8083
8028
  type: Component,
8084
- args: [{ selector: 'lib-app-preset', standalone: false, template: "<div\n class=\"card border-secondary h-100 panel card-intro-preset card-intro-active\"\n [class.card-intro-active]=\"introService.showStep('presets')\"\n>\n <div class=\"card-header d-flex\">\n <div>\n {{ 'designer.preset.title' | translate }}\n </div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"removePreset(); (false)\"\n ><i class=\"fa fa-minus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"addPreset(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of presets -->\n <!-- <tree-root #tree [nodes]=\"treeNodes\" [options]=\"treeOptions\" (activate)=\"onActivate($event)\">\n <ng-template #treeNodeTemplate let-node let-index=\"index\">\n <span>{{ node.data.name }}</span>\n </ng-template>\n </tree-root> -->\n\n <div class=\"list-group\" [sortablejs]=\"projectService.project.presets\">\n @for (item of projectService.project.presets; track item; let i = $index) {\n <div\n class=\"list-group-item\"\n (click)=\"selectPreset(i)\"\n [class.active-light]=\"!projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.active]=\"projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.inactive-list-item]=\"!sceneService.presetIsSelected(item)\"\n >\n <div class=\"row d-flex\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n [disabled]=\"!enableCheckbox()\"\n class=\"form-check-input\"\n id=\"active\"\n [ngModel]=\"sceneService.presetIsSelected(item)\"\n (ngModelChange)=\"activatePreset($event, i)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n <div>\n {{ item.name }}\n </div>\n <div class=\"my-auto ml-auto mr-2 d-flex\">\n <button type=\"button\" class=\"btn btn-secondary btn-sm py-0 px-1\" (click)=\"openSettings(item); (false)\">...</button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n" }]
8085
- }], ctorParameters: () => [{ type: PresetService }, { type: SceneService }, { type: ProjectService }, { type: IntroService }, { type: i1$1.BsModalService }], propDecorators: { tree: [{
8086
- type: ViewChild,
8087
- args: ['tree']
8088
- }] } });
8029
+ args: [{ selector: 'lib-app-preset', standalone: false, template: "<div\n class=\"card border-secondary h-100 panel card-intro-preset card-intro-active\"\n [class.card-intro-active]=\"introService.showStep('presets')\"\n>\n <div class=\"card-header d-flex\">\n <div>\n {{ 'designer.preset.title' | translate }}\n </div>\n <div class=\"ml-auto\">\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"removePreset(); (false)\"\n ><i class=\"fa fa-minus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n <a href=\"#\" class=\"btn btn-secondary m-0, p-0\" (click)=\"addPreset(); (false)\"\n ><i class=\"fa fa-plus-circle fa-fw\" aria-hidden=\"true\"></i\n ></a>\n </div>\n </div>\n\n <div class=\"card-body h-100 p-0\">\n <!-- List of presets -->\n <!-- <lib-tree [nodes]=\"treeNodes\" (activate)=\"onActivate($event)\">\n <ng-template #nodeTemplate let-node>\n <span>{{ node.name }}</span>\n </ng-template>\n </lib-tree> -->\n\n <div class=\"list-group\" [sortablejs]=\"projectService.project.presets\">\n @for (item of projectService.project.presets; track item; let i = $index) {\n <div\n class=\"list-group-item\"\n (click)=\"selectPreset(i)\"\n [class.active-light]=\"!projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.active]=\"projectService.project.previewPreset && item == presetService.selectedPreset\"\n [class.inactive-list-item]=\"!sceneService.presetIsSelected(item)\"\n >\n <div class=\"row d-flex\" style=\"cursor: pointer\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"form-check\">\n <input\n type=\"checkbox\"\n [disabled]=\"!enableCheckbox()\"\n class=\"form-check-input\"\n id=\"active\"\n [ngModel]=\"sceneService.presetIsSelected(item)\"\n (ngModelChange)=\"activatePreset($event, i)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n <div>\n {{ item.name }}\n </div>\n <div class=\"my-auto ml-auto mr-2 d-flex\">\n <button type=\"button\" class=\"btn btn-secondary btn-sm py-0 px-1\" (click)=\"openSettings(item); (false)\">...</button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n" }]
8030
+ }], ctorParameters: () => [{ type: PresetService }, { type: SceneService }, { type: ProjectService }, { type: IntroService }, { type: i1$1.BsModalService }] });
8089
8031
 
8090
8032
  class MasterDimmerComponent {
8091
8033
  constructor(projectService, changeDetectorRef, livePreviewService) {
@@ -8680,11 +8622,11 @@ class DesignerComponent {
8680
8622
  localStorage.setItem('language', language);
8681
8623
  }
8682
8624
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DesignerComponent, deps: [{ token: i2.TranslateService }, { token: ProjectService }, { token: ConfigService }, { token: FixturePoolService }, { token: HotkeyTargetExcludeService }, { token: i1$1.BsModalService }, { token: UserService }, { token: UserEnsureLoginService }, { token: ProjectLoadService }, { token: WarningDialogService }, { token: ErrorDialogService }, { token: FixtureService }, { token: TimelineService }, { token: IntroService }, { token: EffectService }], target: i0.ɵɵFactoryTarget.Component }); }
8683
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DesignerComponent, isStandalone: false, selector: "lib-designer", inputs: { menuHeightPx: "menuHeightPx", externalCompositionsAvailable: "externalCompositionsAvailable", restUrl: "restUrl", enableMediaLibrary: "enableMediaLibrary", loginAvailable: "loginAvailable", shareAvailable: "shareAvailable", languageSwitch: "languageSwitch", livePreview: "livePreview", localProfiles: "localProfiles", intro: "intro", uniqueProjectNames: "uniqueProjectNames", dropzoneChunking: "dropzoneChunking", universes: "universes", freeUniverseEdit: "freeUniverseEdit" }, host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, viewQueries: [{ propertyName: "previewComponent", first: true, predicate: PreviewComponent, descendants: true }, { propertyName: "timelineComponent", first: true, predicate: TimelineComponent, descendants: true }], ngImport: i0, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n @if (configService.shareAvailable) {\n <li class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n } @if (configService.languageSwitch) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n </div>\n </li>\n } @if (configService.loginAvailable && !userService.isLoggedIn()) {\n <li class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n } @if (configService.loginAvailable && userService.isLoggedIn()) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n }\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-preset></lib-app-preset>\n }\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n @if (projectService.project) {\n <div class=\"card border-secondary h-100\" [class.card-intro-active]=\"introService.showStep('preview')\">\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n @if (projectService.project) {\n <div class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n }\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n @if (projectService.project) {\n <div class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-fixture></lib-app-fixture>\n }\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n @if (projectService.project) {\n <lib-app-timeline></lib-app-timeline>\n }\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n\n <div class=\"mt-3\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer{font-size:14px}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}#designer wave canvas{opacity:.2}\n"], dependencies: [{ kind: "directive", type: i3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i10$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: PreviewComponent, selector: "lib-app-preview" }, { kind: "component", type: SceneComponent, selector: "lib-app-scene" }, { kind: "component", type: TimelineComponent, selector: "lib-app-timeline" }, { kind: "component", type: FixtureComponent, selector: "lib-app-fixture" }, { kind: "component", type: FixtureCapabilityComponent, selector: "lib-app-fixture-capability" }, { kind: "component", type: FixtureSettingsComponent, selector: "lib-app-fixture-settings" }, { kind: "component", type: EffectComponent, selector: "lib-app-effect" }, { kind: "component", type: PresetComponent, selector: "lib-app-preset" }, { kind: "component", type: MasterDimmerComponent, selector: "lib-app-master-dimmer" }, { kind: "component", type: FixtureChannelComponent, selector: "lib-app-fixture-channel" }, { kind: "component", type: IntroComponent, selector: "lib-app-intro" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
8625
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DesignerComponent, isStandalone: false, selector: "lib-designer", inputs: { menuHeightPx: "menuHeightPx", externalCompositionsAvailable: "externalCompositionsAvailable", restUrl: "restUrl", enableMediaLibrary: "enableMediaLibrary", loginAvailable: "loginAvailable", shareAvailable: "shareAvailable", languageSwitch: "languageSwitch", livePreview: "livePreview", localProfiles: "localProfiles", intro: "intro", uniqueProjectNames: "uniqueProjectNames", dropzoneChunking: "dropzoneChunking", universes: "universes", freeUniverseEdit: "freeUniverseEdit" }, host: { listeners: { "document:keydown": "handleKeyboardEvent($event)" } }, viewQueries: [{ propertyName: "previewComponent", first: true, predicate: PreviewComponent, descendants: true }, { propertyName: "timelineComponent", first: true, predicate: TimelineComponent, descendants: true }], ngImport: i0, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n @if (configService.shareAvailable) {\n <li class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n } @if (configService.languageSwitch) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('es'); (false)\" target=\"_blank\">Espa\u00F1ol</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('fr'); (false)\" target=\"_blank\">Fran\u00E7ais</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('it'); (false)\" target=\"_blank\">Italiano</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('pt'); (false)\" target=\"_blank\">Portugu\u00EAs</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('zh'); (false)\" target=\"_blank\">\u4E2D\u6587</a>\n </div>\n </li>\n } @if (configService.loginAvailable && !userService.isLoggedIn()) {\n <li class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n } @if (configService.loginAvailable && userService.isLoggedIn()) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n }\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-preset></lib-app-preset>\n }\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n @if (projectService.project) {\n <div class=\"card border-secondary h-100\" [class.card-intro-active]=\"introService.showStep('preview')\">\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n @if (projectService.project) {\n <div class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n }\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n @if (projectService.project) {\n <div class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-fixture></lib-app-fixture>\n }\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n @if (projectService.project) {\n <lib-app-timeline></lib-app-timeline>\n }\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n\n <div class=\"mt-3\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer{font-size:14px}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}#designer wave canvas{opacity:.2}\n"], dependencies: [{ kind: "directive", type: i3.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i10$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "component", type: PreviewComponent, selector: "lib-app-preview" }, { kind: "component", type: SceneComponent, selector: "lib-app-scene" }, { kind: "component", type: TimelineComponent, selector: "lib-app-timeline" }, { kind: "component", type: FixtureComponent, selector: "lib-app-fixture" }, { kind: "component", type: FixtureCapabilityComponent, selector: "lib-app-fixture-capability" }, { kind: "component", type: FixtureSettingsComponent, selector: "lib-app-fixture-settings" }, { kind: "component", type: EffectComponent, selector: "lib-app-effect" }, { kind: "component", type: PresetComponent, selector: "lib-app-preset" }, { kind: "component", type: MasterDimmerComponent, selector: "lib-app-master-dimmer" }, { kind: "component", type: FixtureChannelComponent, selector: "lib-app-fixture-channel" }, { kind: "component", type: IntroComponent, selector: "lib-app-intro" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
8684
8626
  }
8685
8627
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DesignerComponent, decorators: [{
8686
8628
  type: Component,
8687
- args: [{ selector: 'lib-designer', encapsulation: ViewEncapsulation.None, standalone: false, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n @if (configService.shareAvailable) {\n <li class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n } @if (configService.languageSwitch) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n </div>\n </li>\n } @if (configService.loginAvailable && !userService.isLoggedIn()) {\n <li class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n } @if (configService.loginAvailable && userService.isLoggedIn()) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n }\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-preset></lib-app-preset>\n }\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n @if (projectService.project) {\n <div class=\"card border-secondary h-100\" [class.card-intro-active]=\"introService.showStep('preview')\">\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n @if (projectService.project) {\n <div class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n }\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n @if (projectService.project) {\n <div class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-fixture></lib-app-fixture>\n }\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n @if (projectService.project) {\n <lib-app-timeline></lib-app-timeline>\n }\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n\n <div class=\"mt-3\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer{font-size:14px}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}#designer wave canvas{opacity:.2}\n"] }]
8629
+ args: [{ selector: 'lib-designer', encapsulation: ViewEncapsulation.None, standalone: false, template: "<!-- Wrap the whole component inside a div to encapsulate the CSS -->\n\n<!-- 100 % height minus the menu bar above and the gutter size of 13 px -->\n<!-- <div style=\"height: calc(100% - 33px)\"> -->\n<div id=\"designer\" [ngStyle]=\"{ height: 'calc(100% - ' + totalMenuHeightPx + 'px)' }\">\n <!-- Navigation -->\n <nav\n class=\"navbar navbar-expand-lg navbar-light bg-light border-secondary\"\n style=\"border-bottom: 1px solid #444; height: 20px; z-index: 9999\"\n >\n <!-- Menu buttons -->\n <ul class=\"navbar-nav mr-auto\">\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"fileDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n {{ 'designer.navigation.project' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"fileDropdown\">\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectNew(); (false)\"\n ><i class=\"fa fa-fw fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-new' | translate }}</a\n >\n <a class=\"dropdown-item\" href=\"#\" (click)=\"projectOpen(); (false)\"\n ><i class=\"fa fa-fw fa-folder-open-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-open' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSave(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectSaveAs(); (false)\"\n ><i class=\"fa fa-fw fa-floppy-o\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-save-as' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectImport(); (false)\"\n ><i class=\"fa fa-fw fa-download\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-import' | translate }}</a\n >\n <a class=\"dropdown-item d-none d-md-block\" href=\"#\" (click)=\"projectExport(); (false)\"\n ><i class=\"fa fa-fw fa-external-link\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-export' | translate }}</a\n >\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.settings' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"openFixturePool(); (false)\">{{ 'designer.navigation.fixture-pool' | translate }}</a>\n <!-- <a class=\"dropdown-item\" href=\"#\">{{ 'designer.navigation.stage' | translate }}</a> -->\n </div>\n </li>\n <li class=\"nav-item dropdown d-none d-md-block\">\n <a\n class=\"nav-link dropdown-toggle\"\n href=\"#\"\n id=\"settingsDropdown\"\n data-toggle=\"dropdown\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n {{ 'designer.navigation.help' | translate }}\n </a>\n <div class=\"dropdown-menu\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"introService.reset(); (false)\">{{ 'designer.navigation.reset-intro' | translate }}</a>\n <a class=\"dropdown-item\" href=\"https://rocketshow.net/support/\" target=\"_blank\">{{\n 'designer.navigation.support' | translate\n }}</a>\n </div>\n </li>\n </ul>\n\n <ul class=\"navbar-nav\">\n @if (configService.shareAvailable) {\n <li class=\"nav-item d-none d-md-flex\" data-toggle=\"collapse\">\n <a class=\"nav-link text-primary\" (click)=\"projectShare(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-share-alt\" aria-hidden=\"true\"></i> {{ 'designer.navigation.project-share' | translate }}</a\n >\n </li>\n } @if (configService.languageSwitch) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-globe\" aria-hidden=\"true\"></i>\n {{ 'designer.misc.language' | translate }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('de'); (false)\" target=\"_blank\">Deutsch</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('en'); (false)\" target=\"_blank\">English</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('es'); (false)\" target=\"_blank\">Espa\u00F1ol</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('fr'); (false)\" target=\"_blank\">Fran\u00E7ais</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('it'); (false)\" target=\"_blank\">Italiano</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('pt'); (false)\" target=\"_blank\">Portugu\u00EAs</a>\n <a class=\"dropdown-item\" href=\"#\" (click)=\"switchLanguage('zh'); (false)\" target=\"_blank\">\u4E2D\u6587</a>\n </div>\n </li>\n } @if (configService.loginAvailable && !userService.isLoggedIn()) {\n <li class=\"nav-item\" data-toggle=\"collapse\">\n <a class=\"nav-link\" (click)=\"userRegister(); (false)\" routerLinkActive=\"active\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i> {{ 'designer.navigation.login' | translate }}</a\n >\n </li>\n } @if (configService.loginAvailable && userService.isLoggedIn()) {\n <li class=\"nav-item dropdown\">\n <a class=\"nav-link dropdown-toggle\" href=\"#\" id=\"settingsDropdown\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"\n ><i class=\"fa fa-user\" aria-hidden=\"true\"></i>\n {{ userService.username }}\n </a>\n <div class=\"dropdown-menu dropdown-menu-right\" aria-labelledby=\"settingsDropdown\">\n <a class=\"dropdown-item\" href=\"#\" (click)=\"userService.logout(); (false)\" target=\"_blank\"\n ><i class=\"fa fa-sign-out\" aria-hidden=\"true\"></i> {{ 'designer.navigation.logout' | translate }}</a\n >\n </div>\n </li>\n }\n </ul>\n </nav>\n\n <!-- The main content for larger screens -->\n <div class=\"h-100 d-none d-md-block\">\n <div id=\"row1\" class=\"split split-vertical clearfix pt-3 pl-3\">\n <!-- Scenes -->\n <div id=\"scenes\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n\n <!-- Presets -->\n <div id=\"presets\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-preset></lib-app-preset>\n }\n </div>\n\n <!-- 3D preview -->\n <div id=\"preview\" class=\"split split-horizontal h-100 pr-3\">\n @if (projectService.project) {\n <div class=\"card border-secondary h-100\" [class.card-intro-active]=\"introService.showStep('preview')\">\n <div class=\"card-body p-0 h-100\">\n <lib-app-preview class=\"h-100\"></lib-app-preview>\n </div>\n </div>\n }\n </div>\n </div>\n\n <div id=\"row2\" class=\"split split-vertical clearfix px-3 d-flex\" style=\"flex-direction: row\">\n <!-- Menu for the capabilities, channels, effects and settings -->\n @if (projectService.project) {\n <div class=\"col col-auto p-0\" style=\"margin-right: -1px\">\n <div class=\"nav flex-column nav-pills\" id=\"v-pills-tab\" role=\"tablist\" aria-orientation=\"vertical\">\n <a\n class=\"nav-link px-3 active\"\n (click)=\"openTab('capabilities')\"\n id=\"v-pills-capabilities-tab\"\n popover=\"{{ 'designer.misc.capabilities' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-capabilities\"\n role=\"tab\"\n aria-controls=\"v-pills-capabilities\"\n aria-selected=\"true\"\n >\n <i class=\"fa fa-bolt fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('channels')\"\n id=\"v-pills-channels-tab\"\n popover=\"{{ 'designer.misc.channels' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-channels\"\n role=\"tab\"\n aria-controls=\"v-pills-channels\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-sliders fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('effects')\"\n id=\"v-pills-effects-tab\"\n popover=\"{{ 'designer.misc.effects' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-effects\"\n role=\"tab\"\n aria-controls=\"v-pills-effects\"\n aria-selected=\"false\"\n >\n <i class=\"fa fa-magic fa-fw\" aria-hidden=\"true\"></i>\n </a>\n <a\n class=\"nav-link px-3\"\n (click)=\"openTab('settings')\"\n id=\"v-pills-settings-tab\"\n popover=\"{{ 'designer.misc.settings' | translate }}\"\n container=\"body\"\n placement=\"right\"\n triggers=\"mouseenter:mouseleave\"\n data-toggle=\"pill\"\n href=\"#v-pills-settings\"\n role=\"tab\"\n aria-controls=\"v-pills-settings\"\n aria-selected=\"false\"\n style=\"border-top: 1px solid #444\"\n >\n <i class=\"fa fa-cog fa-fw\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n }\n\n <div id=\"capabilities\" class=\"split split-horizontal h-100\" style=\"padding-left: 1rem\">\n @if (projectService.project) {\n <div class=\"row h-100\">\n <!-- Content for the capabilities, channels, effects and settings -->\n <div class=\"col pl-0 h-100\">\n <div class=\"tab-content h-100\" id=\"v-pills-tabContent\">\n <div class=\"tab-pane h-100 show active\" id=\"v-pills-capabilities\" role=\"tabpanel\">\n <lib-app-fixture-capability></lib-app-fixture-capability>\n </div>\n <div class=\"tab-pane h-100 show\" id=\"v-pills-channels\" role=\"tabpanel\">\n <lib-app-fixture-channel></lib-app-fixture-channel>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-effects\" role=\"tabpanel\" aria-labelledby=\"v-pills-profile-tab\">\n <lib-app-effect></lib-app-effect>\n </div>\n <div class=\"tab-pane h-100\" id=\"v-pills-settings\" role=\"tabpanel\" aria-labelledby=\"v-pills-home-tab\">\n <lib-app-fixture-settings></lib-app-fixture-settings>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Fixtures -->\n <div id=\"fixtures\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-fixture></lib-app-fixture>\n }\n </div>\n\n <!-- Master dimmer -->\n <div id=\"masterDimmer\" class=\"split split-horizontal h-100\">\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n </div>\n\n <!-- Timeline -->\n <div id=\"row3\" class=\"split split-vertical clearfix px-3 pb-3\" style=\"padding-bottom: 20px\">\n @if (projectService.project) {\n <lib-app-timeline></lib-app-timeline>\n }\n </div>\n </div>\n\n <!-- The components for small screens -->\n <div class=\"d-md-none p-3\">\n <div>\n @if (projectService.project) {\n <lib-app-master-dimmer></lib-app-master-dimmer>\n }\n </div>\n\n <div class=\"mt-3\">\n @if (projectService.project) {\n <lib-app-scene></lib-app-scene>\n }\n </div>\n </div>\n</div>\n\n<lib-app-intro class=\"d-none d-md-flex\"></lib-app-intro>\n", styles: [".modal-full{max-width:unset!important;margin:1.75rem!important}.modal{z-index:10001}#designer{font-size:14px}#designer .nav-link{cursor:pointer}#designer .dropdown-menu{z-index:100000}#designer .row{flex-wrap:unset}#designer .navbar-nav{flex-direction:row!important}#designer .navbar-expand-lg{flex-flow:row nowrap!important;justify-content:flex-start!important}#designer .navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem!important;padding-left:.5rem!important}#designer .list-group-item.active{color:#fff!important;background-color:#fd7e14!important;border-color:#fd7e14!important}#designer *:focus{outline:none}#designer select{font-size:.8rem;cursor:pointer}#designer input{font-size:.7rem;background-color:transparent;color:#fff;border:1px solid}#designer input,#designer select{border-color:#dee2e6}#designer .list-group-item{padding:.3rem 1.25rem;border-left:none;border-right:none}#designer .nav-pills .nav-link.active,#designer .nav-pills .show>.nav-link{background-color:#444}#designer .nav a,#designer .panel-title .btn-link{color:#fff!important}#designer .accordion-toggle .btn,#designer .accordion-toggle button{padding:0}#designer .card-body{overflow:auto;padding:.8rem}#designer .card-header{margin-bottom:0}#designer .card-header{padding:.4rem}#designer .panel-body{background-color:#303030}#designer .list-group-item.active-light{background-color:#906542;border-color:#906542}#designer .inactive-list-item{opacity:.3}#designer span.bigcheck-target{font-family:FontAwesome}#designer input[type=checkbox].bigcheck{position:relative;left:-999em}#designer input[type=checkbox].bigcheck+span.bigcheck-target:after{content:\"\\f096\"}#designer input[type=checkbox].bigcheck:checked+span.bigcheck-target:after{content:\"\\f046\"}#designer .gutter.gutter-horizontal{cursor:ew-resize}#designer .gutter.gutter-vertical{cursor:ns-resize}#designer .split-horizontal,#designer .gutter.gutter-horizontal{float:left}#designer .split-vertical,#designer .gutter.gutter-horizontal{height:100%}#designer .split{overflow-y:hidden;overflow-x:hidden}#designer .panel{background-color:transparent}#designer .slider{cursor:pointer}#designer .slider-horizontal .slider-track{height:2px!important;margin-top:-2px!important}#designer .slider-vertical .slider-track{width:2px!important;margin-left:4px!important}#designer .slider-track,#designer .slider-track-low,#designer .slider-track-high,#designer .slider-selection{background-color:#fff!important;border-radius:0!important;background-image:none!important;box-shadow:none!important}#designer .slider-handle{width:13px!important;height:13px!important;background-color:#fff!important;background-image:none!important;border:1px solid #303030}#designer .slider-vertical .slider-handle{margin-left:4px!important}#designer .slider-horizontal .slider-handle{margin-top:2px!important}#designer .slider-input{width:35px;margin-left:8px;text-align:center}#designer .slider-input-readonly{width:35px;margin-left:8px;text-align:center;color:#a9a9a9;border-color:gray}#designer .capability-container{padding:0;height:0}#designer accordion-group>div{border:none!important}#designer .popover{background-color:#fff}#designer .popover-body{color:#000}#designer .bs-popover-right .arrow:after,#designer .bs-popover-auto[x-placement^=right] .arrow:after{border-right-color:#fff}#designer .bs-popover-left .arrow:after,#designer .bs-popover-auto[x-placement^=left] .arrow:after{border-left-color:#fff}#designer .bs-popover-bottom .arrow:after,#designer .bs-popover-auto[x-placement^=bottom] .arrow:after{border-bottom-color:#fff}#designer .bs-popover-top .arrow:after,#designer .bs-popover-auto[x-placement^=top] .arrow:after{border-top-color:#fff}#designer .iro__wheel,#designer .iro__slider{cursor:pointer}#designer .pan-tilt-grid path{fill:none;stroke:#fff;stroke-width:10px}#designer .pan-tilt-grid circle{fill:#4682b4;stroke:#fff;stroke-width:3px}#designer .capability{overflow:visible}#designer .capability-deactivated{opacity:.4}#designer .wavesurfer-region{z-index:5!important}#designer .wavesurfer-region[data-region-selected=true]{z-index:6!important}#designer .wavesurfer-region[data-region-preset=true]{height:50%!important;top:50%!important}#designer .wavesurfer-region[data-region-name]:after{content:attr(data-region-name);margin-left:20px}#designer .wavesurfer-handle{width:10px!important;max-width:10px!important;border:1px solid #ddd;background:#0000001a;box-sizing:border-box;opacity:0;cursor:unset!important}#designer .wavesurfer-handle-end{margin-left:-10px}#designer .wavesurfer-region[data-region-selectable=true] .wavesurfer-handle{opacity:1;cursor:col-resize!important}#designer .wavesurfer-handle:before,#designer .wavesurfer-handle:after{content:\"\";display:block;position:absolute;z-index:1;border-top:1px solid #fff;border-bottom:1px solid #fff;height:4px;left:5%;right:5%;top:50%;transform:translateY(-50%)}#designer .wavesurfer-handle:before{margin-top:-3px}#designer timeline{overflow:scroll!important;overflow:-moz-scrollbars-none;-ms-overflow-style:none;scrollbar-width:none;cursor:s-resize}#designer timeline::-webkit-scrollbar{height:0!important}#designer cursor{top:-20px!important}#designer wave{border-right-color:#fd7e14!important;cursor:col-resize}#designer wave canvas{opacity:.2}\n"] }]
8688
8630
  }], ctorParameters: () => [{ type: i2.TranslateService }, { type: ProjectService }, { type: ConfigService }, { type: FixturePoolService }, { type: HotkeyTargetExcludeService }, { type: i1$1.BsModalService }, { type: UserService }, { type: UserEnsureLoginService }, { type: ProjectLoadService }, { type: WarningDialogService }, { type: ErrorDialogService }, { type: FixtureService }, { type: TimelineService }, { type: IntroService }, { type: EffectService }], propDecorators: { menuHeightPx: [{
8689
8631
  type: Input
8690
8632
  }], externalCompositionsAvailable: [{
@@ -8724,6 +8666,344 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8724
8666
  args: ['document:keydown', ['$event']]
8725
8667
  }] } });
8726
8668
 
8669
+ /**
8670
+ * A lightweight, dependency-free tree:
8671
+ * - collapsible folders (closed/open folder icon)
8672
+ * - multi selection (ctrl/cmd to toggle, shift to select a range)
8673
+ * - native HTML5 drag & drop, dropping before/after a node or into a folder,
8674
+ * moving the whole current selection at once
8675
+ */
8676
+ class TreeComponent {
8677
+ constructor() {
8678
+ // the tree data (mutated in place when nodes are dragged around)
8679
+ this.nodes = [];
8680
+ // currently selected nodes (two-way bindable)
8681
+ this.selectedNodes = [];
8682
+ // decide whether a node may be dragged
8683
+ this.allowDrag = () => true;
8684
+ // decide whether the dragged nodes may be dropped onto a target/zone
8685
+ this.allowDrop = () => true;
8686
+ this.selectedNodesChange = new EventEmitter();
8687
+ // a (non-folder) leaf was activated by a plain click
8688
+ this.activate = new EventEmitter();
8689
+ // the tree structure changed because of a drag & drop move
8690
+ this.nodesChange = new EventEmitter();
8691
+ // the visible (expanded) nodes, flattened for rendering
8692
+ this.flatNodes = [];
8693
+ // currently dragged nodes and the live drop indicator
8694
+ this.draggingNodes = [];
8695
+ this.drop = null;
8696
+ // hovering the trailing strip drops at the very end of the root level
8697
+ this.dropTail = false;
8698
+ this.selection = new Set();
8699
+ this.lastClickedIndex = null;
8700
+ this.flatByNode = new Map();
8701
+ }
8702
+ // indentation of one tree level, in px (must match the template/CSS)
8703
+ static { this.INDENT_STEP = 15; }
8704
+ static { this.INDENT_BASE = 4; }
8705
+ indentPx(level) {
8706
+ return this.indent(level) + 'px';
8707
+ }
8708
+ indent(level) {
8709
+ return level * TreeComponent.INDENT_STEP + TreeComponent.INDENT_BASE;
8710
+ }
8711
+ ngOnChanges(changes) {
8712
+ if (changes['selectedNodes']) {
8713
+ this.selection = new Set(this.selectedNodes ?? []);
8714
+ }
8715
+ this.rebuild();
8716
+ }
8717
+ isSelected(node) {
8718
+ return this.selection.has(node);
8719
+ }
8720
+ isDragging(node) {
8721
+ return this.draggingNodes.includes(node);
8722
+ }
8723
+ toggleExpand(node) {
8724
+ node.expanded = !node.expanded;
8725
+ this.rebuild();
8726
+ }
8727
+ // ---- selection / clicking ----------------------------------------------
8728
+ onRowClick(flat, event) {
8729
+ const node = flat.node;
8730
+ const index = this.flatNodes.indexOf(flat);
8731
+ if (event.shiftKey && this.lastClickedIndex !== null) {
8732
+ this.selectRange(this.lastClickedIndex, index, event.ctrlKey || event.metaKey);
8733
+ }
8734
+ else if (event.ctrlKey || event.metaKey) {
8735
+ if (this.selection.has(node)) {
8736
+ this.selection.delete(node);
8737
+ }
8738
+ else {
8739
+ this.selection.add(node);
8740
+ }
8741
+ this.lastClickedIndex = index;
8742
+ }
8743
+ else {
8744
+ // plain click: folders toggle, leaves activate; either way select just this row
8745
+ if (node.isFolder) {
8746
+ this.toggleExpand(node);
8747
+ }
8748
+ this.selection.clear();
8749
+ this.selection.add(node);
8750
+ this.lastClickedIndex = index;
8751
+ if (!node.isFolder) {
8752
+ this.activate.emit(node);
8753
+ }
8754
+ }
8755
+ this.selectedNodesChange.emit([...this.selection]);
8756
+ }
8757
+ selectRange(from, to, additive) {
8758
+ if (!additive) {
8759
+ this.selection.clear();
8760
+ }
8761
+ const [lo, hi] = from <= to ? [from, to] : [to, from];
8762
+ for (let i = lo; i <= hi && i < this.flatNodes.length; i++) {
8763
+ this.selection.add(this.flatNodes[i].node);
8764
+ }
8765
+ }
8766
+ // ---- drag & drop --------------------------------------------------------
8767
+ onDragStart(flat, event) {
8768
+ const node = flat.node;
8769
+ if (!this.allowDrag(node)) {
8770
+ event.preventDefault();
8771
+ return;
8772
+ }
8773
+ // dragging an unselected node makes it the sole selection
8774
+ if (!this.selection.has(node)) {
8775
+ this.selection.clear();
8776
+ this.selection.add(node);
8777
+ this.lastClickedIndex = this.flatNodes.indexOf(flat);
8778
+ this.selectedNodesChange.emit([...this.selection]);
8779
+ }
8780
+ // drag the whole selection, but never a node together with its own ancestor
8781
+ this.draggingNodes = this.removeNested([...this.selection]);
8782
+ if (event.dataTransfer) {
8783
+ event.dataTransfer.effectAllowed = 'move';
8784
+ // required for Firefox to start a native drag
8785
+ event.dataTransfer.setData('text/plain', node.name ?? '');
8786
+ }
8787
+ }
8788
+ onDragOver(flat, event) {
8789
+ if (!this.draggingNodes.length) {
8790
+ return;
8791
+ }
8792
+ const resolved = this.resolveDrop(flat, event.currentTarget, event.clientX, event.clientY);
8793
+ if (!this.canDrop(resolved.ref, resolved.zone)) {
8794
+ this.clearIndicator();
8795
+ return;
8796
+ }
8797
+ // preventDefault marks this as a valid drop location
8798
+ event.preventDefault();
8799
+ if (event.dataTransfer) {
8800
+ event.dataTransfer.dropEffect = 'move';
8801
+ }
8802
+ this.drop = resolved;
8803
+ this.dropTail = false;
8804
+ }
8805
+ onDrop(flat, event) {
8806
+ event.preventDefault();
8807
+ if (this.drop) {
8808
+ this.moveNodes(this.draggingNodes, this.drop.ref, this.drop.zone);
8809
+ this.nodesChange.emit(this.nodes);
8810
+ }
8811
+ this.endDrag();
8812
+ }
8813
+ // The strip below the last row: drop after the last folder, at the root level.
8814
+ // (The last folder has no following row to act as a "before" drop target.)
8815
+ onTailDragOver(event) {
8816
+ if (!this.draggingNodes.length) {
8817
+ return;
8818
+ }
8819
+ event.preventDefault();
8820
+ if (event.dataTransfer) {
8821
+ event.dataTransfer.dropEffect = 'move';
8822
+ }
8823
+ this.drop = null;
8824
+ this.dropTail = true;
8825
+ }
8826
+ onTailDrop(event) {
8827
+ event.preventDefault();
8828
+ if (this.draggingNodes.length) {
8829
+ this.detachAll(this.draggingNodes);
8830
+ this.nodes.push(...this.draggingNodes);
8831
+ this.nodesChange.emit(this.nodes);
8832
+ }
8833
+ this.endDrag();
8834
+ }
8835
+ onDragEnd() {
8836
+ this.endDrag();
8837
+ }
8838
+ endDrag() {
8839
+ this.draggingNodes = [];
8840
+ this.clearIndicator();
8841
+ this.rebuild();
8842
+ }
8843
+ clearIndicator() {
8844
+ this.drop = null;
8845
+ this.dropTail = false;
8846
+ }
8847
+ // Resolve the hovered row + cursor position into a drop target.
8848
+ // - top of a row -> before it
8849
+ // - middle of a folder -> inside it
8850
+ // - bottom of a row -> after it (see afterRow for the inside/outside choice)
8851
+ // An expanded, non-empty folder has no "after" band on its header: dropping
8852
+ // after such a folder happens at the bottom of its last child instead, so the
8853
+ // indicator lands at the folder's visual end rather than under its header.
8854
+ resolveDrop(flat, row, clientX, clientY) {
8855
+ const node = flat.node;
8856
+ const rect = row.getBoundingClientRect();
8857
+ const offset = clientY - rect.top;
8858
+ if (node.isFolder) {
8859
+ if (offset < rect.height * 0.3) {
8860
+ return { row: node, zone: 'before', ref: node, indent: this.indent(flat.level) };
8861
+ }
8862
+ const expandedWithChildren = !!node.expanded && !!node.children?.length;
8863
+ if (expandedWithChildren || offset <= rect.height * 0.7) {
8864
+ return { row: node, zone: 'inside', ref: node, indent: this.indent(flat.level) };
8865
+ }
8866
+ return this.afterRow(flat, clientX, rect.left);
8867
+ }
8868
+ if (offset < rect.height / 2) {
8869
+ return { row: node, zone: 'before', ref: node, indent: this.indent(flat.level) };
8870
+ }
8871
+ return this.afterRow(flat, clientX, rect.left);
8872
+ }
8873
+ // "after" the hovered row. When the row is the last child of its subtree, the
8874
+ // horizontal cursor position chooses the level: keep the node inside next to
8875
+ // the row, or outdent to drop after one of its ancestor folders. The indicator
8876
+ // stays at this row's bottom edge but is indented to the chosen level.
8877
+ afterRow(flat, clientX, rowLeft) {
8878
+ const next = this.flatNodes[this.flatNodes.indexOf(flat) + 1];
8879
+ // not the last node of a subtree -> unambiguous "after this row"
8880
+ if (next && next.level >= flat.level) {
8881
+ return { row: flat.node, zone: 'after', ref: flat.node, indent: this.indent(flat.level) };
8882
+ }
8883
+ // last child: pick a drop level between the next visible row's level (how far
8884
+ // we may outdent) and this row's own level, from the cursor's x position
8885
+ const minLevel = next ? next.level : 0;
8886
+ const level = Math.max(minLevel, Math.min(flat.level, Math.round((clientX - rowLeft - TreeComponent.INDENT_BASE) / TreeComponent.INDENT_STEP)));
8887
+ // walk up to the ancestor sitting at the chosen level
8888
+ let ancestor = flat;
8889
+ while (ancestor && ancestor.level > level) {
8890
+ ancestor = ancestor.parent ? this.flatByNode.get(ancestor.parent) : undefined;
8891
+ }
8892
+ return { row: flat.node, zone: 'after', ref: ancestor?.node ?? flat.node, indent: this.indent(level) };
8893
+ }
8894
+ canDrop(ref, zone) {
8895
+ if (this.draggingNodes.includes(ref)) {
8896
+ return false;
8897
+ }
8898
+ // cannot drop a node into its own subtree
8899
+ if (this.draggingNodes.some((dragged) => this.contains(dragged, ref))) {
8900
+ return false;
8901
+ }
8902
+ if (zone === 'inside' && !ref.isFolder) {
8903
+ return false;
8904
+ }
8905
+ return this.allowDrop(this.draggingNodes, ref, zone);
8906
+ }
8907
+ moveNodes(dragged, ref, zone) {
8908
+ this.detachAll(dragged);
8909
+ if (zone === 'inside') {
8910
+ ref.children = ref.children ?? [];
8911
+ ref.children.push(...dragged);
8912
+ ref.isFolder = true;
8913
+ ref.expanded = true;
8914
+ return;
8915
+ }
8916
+ const location = this.locate(ref);
8917
+ if (!location) {
8918
+ this.nodes.push(...dragged);
8919
+ return;
8920
+ }
8921
+ const insertAt = location.index + (zone === 'after' ? 1 : 0);
8922
+ location.list.splice(insertAt, 0, ...dragged);
8923
+ }
8924
+ // detach every dragged node from its current parent (re-locate each time, so
8925
+ // indices stay correct while the arrays are being spliced)
8926
+ detachAll(dragged) {
8927
+ for (const node of dragged) {
8928
+ const location = this.locate(node);
8929
+ if (location) {
8930
+ location.list.splice(location.index, 1);
8931
+ }
8932
+ }
8933
+ }
8934
+ // ---- tree helpers -------------------------------------------------------
8935
+ rebuild() {
8936
+ this.flatNodes = [];
8937
+ this.flatByNode.clear();
8938
+ this.flatten(this.nodes ?? [], 0, null);
8939
+ }
8940
+ flatten(list, level, parent) {
8941
+ for (const node of list) {
8942
+ const flat = { node, level, parent };
8943
+ this.flatNodes.push(flat);
8944
+ this.flatByNode.set(node, flat);
8945
+ if (node.isFolder && node.expanded && node.children?.length) {
8946
+ this.flatten(node.children, level + 1, node);
8947
+ }
8948
+ }
8949
+ }
8950
+ // drop nodes that are already contained in another node of the set
8951
+ removeNested(nodes) {
8952
+ return nodes.filter((node) => !nodes.some((other) => other !== node && this.contains(other, node)));
8953
+ }
8954
+ // is `node` somewhere inside `ancestor`'s subtree?
8955
+ contains(ancestor, node) {
8956
+ if (!ancestor.children) {
8957
+ return false;
8958
+ }
8959
+ for (const child of ancestor.children) {
8960
+ if (child === node || this.contains(child, node)) {
8961
+ return true;
8962
+ }
8963
+ }
8964
+ return false;
8965
+ }
8966
+ // find the array and index that currently hold `target`
8967
+ locate(target, list = this.nodes) {
8968
+ for (let i = 0; i < list.length; i++) {
8969
+ if (list[i] === target) {
8970
+ return { list, index: i };
8971
+ }
8972
+ const children = list[i].children;
8973
+ if (children?.length) {
8974
+ const found = this.locate(target, children);
8975
+ if (found) {
8976
+ return found;
8977
+ }
8978
+ }
8979
+ }
8980
+ return null;
8981
+ }
8982
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: TreeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8983
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: TreeComponent, isStandalone: false, selector: "lib-tree", inputs: { nodes: "nodes", selectedNodes: "selectedNodes", allowDrag: "allowDrag", allowDrop: "allowDrop" }, outputs: { selectedNodesChange: "selectedNodesChange", activate: "activate", nodesChange: "nodesChange" }, queries: [{ propertyName: "nodeTemplate", first: true, predicate: ["nodeTemplate"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"tree\" (dragend)=\"onDragEnd()\">\n @for (flat of flatNodes; track flat.node) {\n <div\n class=\"tree-node\"\n [class.selected]=\"isSelected(flat.node)\"\n [class.dragging]=\"isDragging(flat.node)\"\n [class.drop-before]=\"drop?.row === flat.node && drop?.zone === 'before'\"\n [class.drop-after]=\"drop?.row === flat.node && drop?.zone === 'after'\"\n [class.drop-inside]=\"drop?.row === flat.node && drop?.zone === 'inside'\"\n [style.--tree-indent]=\"indentPx(flat.level)\"\n [style.--tree-drop-indent]=\"drop?.row === flat.node ? drop.indent + 'px' : null\"\n [attr.draggable]=\"allowDrag(flat.node)\"\n (click)=\"onRowClick(flat, $event)\"\n (dragstart)=\"onDragStart(flat, $event)\"\n (dragover)=\"onDragOver(flat, $event)\"\n (drop)=\"onDrop(flat, $event)\"\n >\n <i\n class=\"tree-icon fa\"\n [class.fa-folder-open-o]=\"flat.node.isFolder && flat.node.expanded\"\n [class.fa-folder-o]=\"flat.node.isFolder && !flat.node.expanded\"\n [class.fa-file-o]=\"!flat.node.isFolder\"\n aria-hidden=\"true\"\n ></i>\n <span class=\"tree-label\">\n <ng-container *ngTemplateOutlet=\"nodeTemplate || defaultTemplate; context: { $implicit: flat.node, node: flat.node }\"></ng-container>\n </span>\n </div>\n }\n\n <div class=\"tree-tail\" [class.drop-tail]=\"dropTail\" (dragover)=\"onTailDragOver($event)\" (drop)=\"onTailDrop($event)\"></div>\n</div>\n\n<ng-template #defaultTemplate let-node>{{ node.name }}</ng-template>\n", styles: [":host{display:block}.tree{display:flex;flex-direction:column;padding:5px;-webkit-user-select:none;user-select:none}.tree-node{position:relative;flex:0 0 auto;display:flex;align-items:center;height:23px;line-height:23px;padding-left:var(--tree-indent, 4px);padding-right:4px;cursor:pointer;white-space:nowrap}.tree-node:hover{background-color:#ffffff0f}.tree-node.selected{background-color:#906543}.tree-node.dragging{opacity:.4}.tree-node.drop-before,.tree-node.drop-after,.tree-node.drop-inside{z-index:1}.tree-icon{flex:0 0 auto;width:16px;margin-right:5px;text-align:center}.tree-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}.tree-node.drop-before:before,.tree-node.drop-after:after{content:\"\";position:absolute;left:var(--tree-drop-indent, var(--tree-indent, 4px));right:4px;height:2px;background-color:#d39661;pointer-events:none}.tree-node.drop-before:before{top:-1px}.tree-node.drop-after:after{bottom:-1px}.tree-node.drop-inside{outline:2px solid #d39661;outline-offset:-2px}.tree-tail{flex:1 1 auto;min-height:16px}.tree-tail.drop-tail:before{content:\"\";display:block;height:2px;margin:0 4px;background-color:#d39661}\n"], dependencies: [{ kind: "directive", type: i10$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
8984
+ }
8985
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: TreeComponent, decorators: [{
8986
+ type: Component,
8987
+ args: [{ selector: 'lib-tree', standalone: false, template: "<div class=\"tree\" (dragend)=\"onDragEnd()\">\n @for (flat of flatNodes; track flat.node) {\n <div\n class=\"tree-node\"\n [class.selected]=\"isSelected(flat.node)\"\n [class.dragging]=\"isDragging(flat.node)\"\n [class.drop-before]=\"drop?.row === flat.node && drop?.zone === 'before'\"\n [class.drop-after]=\"drop?.row === flat.node && drop?.zone === 'after'\"\n [class.drop-inside]=\"drop?.row === flat.node && drop?.zone === 'inside'\"\n [style.--tree-indent]=\"indentPx(flat.level)\"\n [style.--tree-drop-indent]=\"drop?.row === flat.node ? drop.indent + 'px' : null\"\n [attr.draggable]=\"allowDrag(flat.node)\"\n (click)=\"onRowClick(flat, $event)\"\n (dragstart)=\"onDragStart(flat, $event)\"\n (dragover)=\"onDragOver(flat, $event)\"\n (drop)=\"onDrop(flat, $event)\"\n >\n <i\n class=\"tree-icon fa\"\n [class.fa-folder-open-o]=\"flat.node.isFolder && flat.node.expanded\"\n [class.fa-folder-o]=\"flat.node.isFolder && !flat.node.expanded\"\n [class.fa-file-o]=\"!flat.node.isFolder\"\n aria-hidden=\"true\"\n ></i>\n <span class=\"tree-label\">\n <ng-container *ngTemplateOutlet=\"nodeTemplate || defaultTemplate; context: { $implicit: flat.node, node: flat.node }\"></ng-container>\n </span>\n </div>\n }\n\n <div class=\"tree-tail\" [class.drop-tail]=\"dropTail\" (dragover)=\"onTailDragOver($event)\" (drop)=\"onTailDrop($event)\"></div>\n</div>\n\n<ng-template #defaultTemplate let-node>{{ node.name }}</ng-template>\n", styles: [":host{display:block}.tree{display:flex;flex-direction:column;padding:5px;-webkit-user-select:none;user-select:none}.tree-node{position:relative;flex:0 0 auto;display:flex;align-items:center;height:23px;line-height:23px;padding-left:var(--tree-indent, 4px);padding-right:4px;cursor:pointer;white-space:nowrap}.tree-node:hover{background-color:#ffffff0f}.tree-node.selected{background-color:#906543}.tree-node.dragging{opacity:.4}.tree-node.drop-before,.tree-node.drop-after,.tree-node.drop-inside{z-index:1}.tree-icon{flex:0 0 auto;width:16px;margin-right:5px;text-align:center}.tree-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis}.tree-node.drop-before:before,.tree-node.drop-after:after{content:\"\";position:absolute;left:var(--tree-drop-indent, var(--tree-indent, 4px));right:4px;height:2px;background-color:#d39661;pointer-events:none}.tree-node.drop-before:before{top:-1px}.tree-node.drop-after:after{bottom:-1px}.tree-node.drop-inside{outline:2px solid #d39661;outline-offset:-2px}.tree-tail{flex:1 1 auto;min-height:16px}.tree-tail.drop-tail:before{content:\"\";display:block;height:2px;margin:0 4px;background-color:#d39661}\n"] }]
8988
+ }], propDecorators: { nodes: [{
8989
+ type: Input
8990
+ }], selectedNodes: [{
8991
+ type: Input
8992
+ }], allowDrag: [{
8993
+ type: Input
8994
+ }], allowDrop: [{
8995
+ type: Input
8996
+ }], selectedNodesChange: [{
8997
+ type: Output
8998
+ }], activate: [{
8999
+ type: Output
9000
+ }], nodesChange: [{
9001
+ type: Output
9002
+ }], nodeTemplate: [{
9003
+ type: ContentChild,
9004
+ args: ['nodeTemplate']
9005
+ }] } });
9006
+
8727
9007
  class DesignerModule {
8728
9008
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DesignerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
8729
9009
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.16", ngImport: i0, type: DesignerModule, declarations: [DesignerComponent,
@@ -8765,7 +9045,8 @@ class DesignerModule {
8765
9045
  FixturePoolCreateFromFileComponent,
8766
9046
  FixturePoolEditUniversesComponent,
8767
9047
  DropzoneComponent,
8768
- SortablejsDirective], imports: [i3.RouterModule, BrowserModule,
9048
+ SortablejsDirective,
9049
+ TreeComponent], imports: [i3.RouterModule, BrowserModule,
8769
9050
  BrowserAnimationsModule,
8770
9051
  FormsModule,
8771
9052
  NgxBootstrapSliderModule,
@@ -8773,7 +9054,7 @@ class DesignerModule {
8773
9054
  AccordionModule,
8774
9055
  PopoverModule,
8775
9056
  TypeaheadModule,
8776
- DropzoneModule, i3$1.ToastrModule, TreeModule], exports: [DesignerComponent] }); }
9057
+ DropzoneModule, i3$1.ToastrModule], exports: [DesignerComponent] }); }
8777
9058
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DesignerModule, providers: [provideHttpClient(withInterceptorsFromDi())], imports: [RouterModule.forRoot([], {}),
8778
9059
  BrowserModule,
8779
9060
  BrowserAnimationsModule,
@@ -8786,8 +9067,7 @@ class DesignerModule {
8786
9067
  DropzoneModule,
8787
9068
  ToastrModule.forRoot({
8788
9069
  newestOnTop: true,
8789
- }),
8790
- TreeModule] }); }
9070
+ })] }); }
8791
9071
  }
8792
9072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DesignerModule, decorators: [{
8793
9073
  type: NgModule,
@@ -8833,6 +9113,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8833
9113
  FixturePoolEditUniversesComponent,
8834
9114
  DropzoneComponent,
8835
9115
  SortablejsDirective,
9116
+ TreeComponent,
8836
9117
  ],
8837
9118
  exports: [DesignerComponent],
8838
9119
  imports: [
@@ -8849,7 +9130,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
8849
9130
  ToastrModule.forRoot({
8850
9131
  newestOnTop: true,
8851
9132
  }),
8852
- TreeModule,
8853
9133
  ],
8854
9134
  providers: [provideHttpClient(withInterceptorsFromDi())],
8855
9135
  }]