@stemy/ngx-utils 19.7.0 → 19.7.1
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.
- package/fesm2022/stemy-ngx-utils.mjs +129 -63
- package/fesm2022/stemy-ngx-utils.mjs.map +1 -1
- package/ngx-utils/common-types.d.ts +32 -16
- package/ngx-utils/components/dynamic-table/dynamic-table.component.d.ts +10 -5
- package/ngx-utils/components/interactive-canvas/interactive-canvas.component.d.ts +19 -12
- package/ngx-utils/components/interactive-canvas/interactive-item.component.d.ts +5 -3
- package/ngx-utils/utils/math.utils.d.ts +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +1 -1
|
@@ -4,7 +4,7 @@ import * as i0 from '@angular/core';
|
|
|
4
4
|
import { InjectionToken, PLATFORM_ID, Inject, Injectable, Optional, Injector, untracked, computed, signal, inject, DestroyRef, isDevMode, ErrorHandler, EventEmitter, createComponent, NgZone, Pipe, input, output, ChangeDetectorRef, ElementRef, effect, HostListener, Directive, Input, HostBinding, Output, TemplateRef, ChangeDetectionStrategy, ViewEncapsulation, Component, ViewChild, forwardRef, ContentChild, ContentChildren, model, contentChildren, provideAppInitializer, makeEnvironmentProviders, NgModule } from '@angular/core';
|
|
5
5
|
import * as i2 from '@angular/router';
|
|
6
6
|
import { ActivatedRouteSnapshot, Scroll, NavigationEnd, Router, DefaultUrlSerializer, UrlTree, UrlSegmentGroup, UrlSegment, UrlSerializer, ROUTES } from '@angular/router';
|
|
7
|
-
import { BehaviorSubject, Observable, firstValueFrom, Subject, Subscription, from, delay, timer, TimeoutError, combineLatest, lastValueFrom } from 'rxjs';
|
|
7
|
+
import { BehaviorSubject, Observable, firstValueFrom, Subject, Subscription, from, delay, timer, TimeoutError, combineLatest, of, lastValueFrom } from 'rxjs';
|
|
8
8
|
import { skipWhile, debounceTime, distinctUntilChanged, map, filter, mergeMap, timeout } from 'rxjs/operators';
|
|
9
9
|
import * as i1$3 from '@angular/common';
|
|
10
10
|
import { isPlatformBrowser, isPlatformServer, DOCUMENT, APP_BASE_HREF, CommonModule } from '@angular/common';
|
|
@@ -2158,10 +2158,10 @@ class LoaderUtils {
|
|
|
2158
2158
|
}
|
|
2159
2159
|
}
|
|
2160
2160
|
|
|
2161
|
+
const EPSILON = 1e-9;
|
|
2161
2162
|
class MathUtils {
|
|
2162
|
-
static { this.EPSILON = 1e-9; }
|
|
2163
2163
|
static equal(a, b, epsilon = null) {
|
|
2164
|
-
epsilon = ObjectUtils.isNumber(epsilon) ? epsilon :
|
|
2164
|
+
epsilon = ObjectUtils.isNumber(epsilon) ? epsilon : EPSILON;
|
|
2165
2165
|
return Math.abs(a - b) < epsilon;
|
|
2166
2166
|
}
|
|
2167
2167
|
static clamp(value, min, max) {
|
|
@@ -7281,6 +7281,9 @@ class DynamicTableComponent {
|
|
|
7281
7281
|
this.testId = "table";
|
|
7282
7282
|
this.titlePrefix = "label";
|
|
7283
7283
|
this.realColumns = {};
|
|
7284
|
+
this.cols = [];
|
|
7285
|
+
this.sortable = false;
|
|
7286
|
+
this.localData = [];
|
|
7284
7287
|
}
|
|
7285
7288
|
setProperty(name, value) {
|
|
7286
7289
|
const elem = this.element.nativeElement;
|
|
@@ -7305,6 +7308,9 @@ class DynamicTableComponent {
|
|
|
7305
7308
|
ngAfterViewInit() {
|
|
7306
7309
|
this.rowTemplate = this.rowTemplate || this.defaultRowTemplate;
|
|
7307
7310
|
}
|
|
7311
|
+
ngOnDestroy() {
|
|
7312
|
+
this.subscription?.unsubscribe();
|
|
7313
|
+
}
|
|
7308
7314
|
ngOnChanges(changes) {
|
|
7309
7315
|
const orderBy = this.orderBy;
|
|
7310
7316
|
if (changes.columns) {
|
|
@@ -7324,6 +7330,7 @@ class DynamicTableComponent {
|
|
|
7324
7330
|
this.cols = Object.keys(this.realColumns);
|
|
7325
7331
|
const sortable = this.cols.filter(c => this.realColumns[c].sort);
|
|
7326
7332
|
const query = this.query || {};
|
|
7333
|
+
this.sortable = sortable.length > 0;
|
|
7327
7334
|
this.orderBy = sortable.includes(this.orderBy) ? this.orderBy : sortable[0] || null;
|
|
7328
7335
|
this.query = this.cols.reduce((res, col) => {
|
|
7329
7336
|
const value = query[col];
|
|
@@ -7337,11 +7344,17 @@ class DynamicTableComponent {
|
|
|
7337
7344
|
this.hasQuery = this.cols.some(col => this.realColumns[col].filter);
|
|
7338
7345
|
if (changes.orderBy && this.realColumns && this.cols) {
|
|
7339
7346
|
const sortable = this.cols.filter(c => this.realColumns[c].sort);
|
|
7347
|
+
this.sortable = sortable.length > 0;
|
|
7340
7348
|
this.orderBy = sortable.includes(this.orderBy) ? this.orderBy : sortable[0] || null;
|
|
7341
7349
|
}
|
|
7342
7350
|
if (!changes.data && !changes.parallelData && !changes.dataLoader && !changes.itemsPerPage && !changes.orderDescending && orderBy === this.orderBy)
|
|
7343
7351
|
return;
|
|
7344
|
-
this.
|
|
7352
|
+
const source = this.data instanceof Observable ? this.data : of(this.data || []);
|
|
7353
|
+
this.subscription?.unsubscribe();
|
|
7354
|
+
this.subscription = source.subscribe(data => {
|
|
7355
|
+
this.localData = data;
|
|
7356
|
+
this.refresh();
|
|
7357
|
+
});
|
|
7345
7358
|
}
|
|
7346
7359
|
onDragStart(ev, elem, item) {
|
|
7347
7360
|
if (!elem || !item || !ObjectUtils.isFunction(this.dragStartFn) || !this.dragStartFn({ ev, elem, item })) {
|
|
@@ -7443,21 +7456,21 @@ class DynamicTableComponent {
|
|
|
7443
7456
|
this.itemsPerPage = count;
|
|
7444
7457
|
this.refresh();
|
|
7445
7458
|
}
|
|
7446
|
-
loadLocalData(page, rowsPerPage, orderBy, orderDescending, filter) {
|
|
7447
|
-
if (!this.
|
|
7448
|
-
return
|
|
7459
|
+
async loadLocalData(page, rowsPerPage, orderBy, orderDescending, filter) {
|
|
7460
|
+
if (!this.localData) {
|
|
7461
|
+
return {
|
|
7449
7462
|
total: 0,
|
|
7450
7463
|
items: []
|
|
7451
|
-
}
|
|
7464
|
+
};
|
|
7452
7465
|
}
|
|
7453
7466
|
const compare = orderDescending
|
|
7454
7467
|
? (a, b) => DynamicTableComponent.compare(orderBy, b, a)
|
|
7455
7468
|
: (a, b) => DynamicTableComponent.compare(orderBy, a, b);
|
|
7456
7469
|
const from = (page - 1) * rowsPerPage;
|
|
7457
|
-
const dataLength = this.
|
|
7470
|
+
const dataLength = this.localData.length;
|
|
7458
7471
|
const length = Math.min(rowsPerPage, dataLength - from);
|
|
7459
7472
|
const parallelData = this.parallelData || [];
|
|
7460
|
-
let data = this.
|
|
7473
|
+
let data = this.localData.map((item, ix) => {
|
|
7461
7474
|
return new PaginationItemContext(item, parallelData[ix] || {}, dataLength, ix, ix);
|
|
7462
7475
|
});
|
|
7463
7476
|
if (ObjectUtils.isString(filter) && filter.length > 0) {
|
|
@@ -7466,19 +7479,20 @@ class DynamicTableComponent {
|
|
|
7466
7479
|
}
|
|
7467
7480
|
const items = orderBy ? data.sort(compare).splice(from, length) : data.splice(from, length);
|
|
7468
7481
|
items.forEach((context, ix) => {
|
|
7469
|
-
context.index =
|
|
7482
|
+
context.index = ix;
|
|
7483
|
+
context.dataIndex = from + ix;
|
|
7470
7484
|
});
|
|
7471
|
-
return
|
|
7485
|
+
return {
|
|
7472
7486
|
total: dataLength,
|
|
7473
7487
|
items: items
|
|
7474
|
-
}
|
|
7488
|
+
};
|
|
7475
7489
|
}
|
|
7476
7490
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicTableComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7477
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DynamicTableComponent, isStandalone: false, selector: "dynamic-table", inputs: { dataLoader: "dataLoader", data: "data", selected: "selected", page: "page", urlParam: "urlParam", parallelData: "parallelData", columns: "columns", showFilter: "showFilter", filterLabel: "filterLabel", placeholder: "placeholder", showItems: "showItems", itemsPerPage: "itemsPerPage", updateTime: "updateTime", filterTime: "filterTime", maxPages: "maxPages", directionLinks: "directionLinks", boundaryLinks: "boundaryLinks", orderBy: "orderBy", orderDescending: "orderDescending", testId: "testId", titlePrefix: "titlePrefix", dragStartFn: "dragStartFn", dragEnterFn: "dragEnterFn", dropFn: "dropFn" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: ["rowTemplate"], descendants: true, static: true }, { propertyName: "wrapperTemplate", first: true, predicate: ["wrapperTemplate"], descendants: true, static: true }, { propertyName: "templateDirectives", predicate: DynamicTableTemplateDirective }], viewQueries: [{ propertyName: "columnsTemplate", first: true, predicate: ["columnsTemplate"], descendants: true, static: true }, { propertyName: "defaultRowTemplate", first: true, predicate: ["defaultRowTemplate"], descendants: true, static: true }, { propertyName: "defaultWrapperTemplate", first: true, predicate: ["defaultWrapperTemplate"], descendants: true, static: true }, { propertyName: "pagination", first: true, predicate: ["pagination"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-template #columnTemplate let-context let-column=\"column\" let-template=\"template\">\n <ng-template #defaultTemplate let-column=\"column\" let-item=\"item\">\n <span>{{ item[column] == undefined || item[column] == null ? '-' : item[column] }}</span>\n </ng-template>\n <ng-template #pureTemplate>\n <ng-container [ngxTemplateOutlet]=\"template.ref\" [context]=\"context\"></ng-container>\n </ng-template>\n <td [ngClass]=\"'column-' + column\"\n [attr.data-testid]=\"testId + '-' + column + '-' + context.rowIndex\"\n *ngIf=\"!template || !template.pure; else pureTemplate\">\n <ng-container [ngxTemplateOutlet]=\"!template ? defaultTemplate : template.ref\"\n [context]=\"context\"></ng-container>\n </td>\n</ng-template>\n\n<ng-template #columnsTemplate let-context>\n <ng-container *ngFor=\"let column of cols\"\n [ngxTemplateOutlet]=\"columnTemplate\"\n [context]=\"context\"\n [additionalContext]=\"{\n template: templates[column],\n column: column\n }\"></ng-container>\n</ng-template>\n\n<ng-template #defaultRowTemplate let-context>\n <tr #elem\n [draggable]=\"!!dragStartFn\"\n [ngClass]=\"{active: selected === context.item}\"\n (dragstart)=\"onDragStart($event, elem, context.item)\"\n (dragenter)=\"onDragEnter($event, elem, context.item)\"\n (dragleave)=\"onDragLeave($event, elem)\"\n (drop)=\"onDrop($event, elem, context.item)\">\n <ng-container [ngxTemplateOutlet]=\"columnsTemplate\" [context]=\"context\"></ng-container>\n </tr>\n</ng-template>\n\n<ng-template #headerTemplate let-column=\"column\" let-toggle=\"toggle\">\n <ng-template #defaultCol>\n <span>{{ realColumns[column].title | translate }}</span>\n </ng-template>\n <ng-template #emptyCol>\n <span>-</span>\n </ng-template>\n <ng-container *ngIf=\"realColumns[column]; else emptyCol\">\n <a *ngIf=\"realColumns[column].sort; else defaultCol\"\n [ngClass]=\"['sort', orderBy !== column ? '' : (orderDescending ? 'sort-desc' : 'sort-asc')]\"\n (click)=\"setSorting(column, toggle)\">\n <span>{{ realColumns[column].title | translate }}</span>\n </a>\n </ng-container>\n</ng-template>\n\n<div class=\"dynamic-table\">\n <div class=\"table-features-row\">\n <ng-content select=\"[table-features-before]\"></ng-content>\n <div class=\"table-input-wrap table-search-filter\" *ngIf=\"showFilter\">\n <label *ngIf=\"filterLabel\" [attr.for]=\"tableId\">\n {{ filterLabel | translate }}\n </label>\n <input type=\"text\"\n class=\"search-input\"\n [attr.id]=\"tableId\"\n [attr.data-testid]=\"testId + '-filter-input'\"\n [placeholder]=\"placeholder | translate\"\n [ngModel]=\"filter\"\n (ngModelChange)=\"setFilter($event)\"/>\n </div>\n <dropdown-box componentClass=\"sort-dropdown\" #sortDd>\n <ng-container toggle-content\n [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: orderBy, toggle: sortDd}\"></ng-container>\n <ul>\n <ng-container *ngFor=\"let column of cols\">\n <li [ngClass]=\"'sort-column sort-' + column\" *ngIf=\"realColumns[column].sort\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <div class=\"table-input-wrap table-items-count\" *ngIf=\"showItems\">\n <label>\n {{ 'label.items.before' | translate }}\n </label>\n <dropdown-box>\n <ng-container toggle-content>\n {{ itemsPerPage }}\n </ng-container>\n <ul>\n <ng-container *ngFor=\"let count of showItems\">\n <li [ngClass]=\"'item-count count-' + count\" (click)=\"setItemsPerPage(count)\">\n {{ count }}\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <label>\n {{ 'label.items.after' | translate }}\n </label>\n </div>\n <ng-content select=\"[table-features-after]\"></ng-content>\n </div>\n <div class=\"table-content-row\"\n #pagination=\"pagination\"\n [pagination]=\"loadData\"\n [page]=\"page\"\n [itemsPerPage]=\"itemsPerPage\"\n [updateTime]=\"updateTime\">\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n <div class=\"table-responsive\">\n <ng-template #defaultWrapperTemplate>\n <table class=\"table table-striped\">\n <thead>\n <tr>\n <th *ngFor=\"let column of cols\" [ngClass]=\"'header-column column-' + column\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </th>\n </tr>\n <tr *ngIf=\"hasQuery\">\n <th *ngFor=\"let column of cols\" [ngClass]=\"['column-' + column, 'filter-column']\">\n <ng-container *ngIf=\"realColumns[column].filter\" [ngSwitch]=\"realColumns[column].filterType\">\n <ng-container *ngSwitchCase=\"'enum'\">\n <ng-template #optionItem let-option=\"option\">\n {{ (realColumns[column].enumPrefix ? realColumns[column].enumPrefix + '.' + option : option) | translate }}\n </ng-template>\n <dropdown-box componentClass=\"filter-box\"\n [ngClass]=\"'filter-box-' + column\" [closeInside]=\"false\">\n <ng-container toggle-content>\n <span class=\"toggle-placeholder\" *ngIf=\"!query[column]\">\n {{ realColumns[column].title | translate }}\n </span>\n <span [ngClass]=\"['option-' + option, column + '-option-' + option, option]\"\n *ngFor=\"let option of query[column] | values; let ix = index\">\n <ng-container *ngIf=\"ix > 0\">, </ng-container>\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </span>\n </ng-container>\n <ul>\n <li [ngClass]=\"[column + '-option', 'option-' + option, option]\"\n (click)=\"setQueryValue(column, option)\"\n *ngFor=\"let option of realColumns[column].enum\">\n <a [ngClass]=\"'toggle-link-' + column\">\n <input type=\"checkbox\" [checked]=\"query[column] | includes: option\">\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </a>\n </li>\n </ul>\n </dropdown-box>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input type=\"checkbox\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <input class=\"search-input\"\n type=\"text\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n </ng-container>\n </th>\n </tr>\n </thead>\n <tbody>\n <ng-container *paginationItem=\"let context\"\n [ngxTemplateOutlet]=\"rowTemplate\"\n [context]=\"context\"\n [additionalContext]=\"this\"></ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <div class=\"table-wrapper\">\n <ng-content select=\"[table-top]\"></ng-content>\n <ng-container [ngxTemplateOutlet]=\"wrapperTemplate || defaultWrapperTemplate\"\n [context]=\"this\"></ng-container>\n <ng-content select=\"[table-bottom]\"></ng-content>\n </div>\n </div>\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n </div>\n</div>\n", styles: [".dynamic-table{--table-bg: transparent;--table-stripe-bg: rgba(210, 210, 210, .35);--border-size: 1px;--border-color: #ced4da;--bg-color: #ffffff;--text-color: #151515;--highlight-color: var(--primary-color, #888888);--highlight-text-color: #ffffff;--display-toggle: none;--arrow-size: 6px;--arrow-rotation: 90;--arrow-space: calc(var(--arrow-size) * .5 + 1px);--arrow-color: #c6c6c6}.dynamic-table *{box-sizing:border-box}.dynamic-table .search-input{background:var(--bg-color);color:var(--text-color);border:var(--border-size) solid var(--border-color);border-radius:5px;padding:6px 12px;-webkit-user-select:none;user-select:none;font-weight:400;font-size:var(--table-input-font-size, 15px);line-height:var(--table-input-line-height, 18px);outline:none}.dynamic-table .search-input .toggle-placeholder,.dynamic-table .search-input ::placeholder{color:#495057}.dynamic-table .table-responsive{border:1px solid var(--border-color);overflow:hidden;overflow-x:auto;margin-bottom:1rem}.dynamic-table .table-features-row:not(:empty){display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:20px}.dynamic-table .table-content-row{position:relative}.dynamic-table .sort-dropdown{display:none}.dynamic-table .table-input-wrap{display:flex;align-items:center;justify-content:flex-end;gap:5px}.dynamic-table .table-input-wrap>label{margin:0;font-weight:700}.dynamic-table .table-input-wrap>input{max-width:400px}.dynamic-table .table-items-count{flex:1}.dynamic-table .table-wrapper{position:relative}.dynamic-table table.table{border-collapse:collapse;margin:0;width:100%;font-family:inherit;font-size:inherit}.dynamic-table table.table th{text-align:left}.dynamic-table table.table th,.dynamic-table table.table td{text-align:left;padding:6px 12px;border:1px solid var(--border-color);vertical-align:middle;white-space:nowrap;width:var(--cell-width, 25%);min-width:fit-content}.dynamic-table table.table-sm th,.dynamic-table table.table-sm td{font-size:var(--font-size-sm);padding:4px 6px}.dynamic-table table.table thead th{font-weight:500}.dynamic-table table.table thead th .dropdown-box{display:block;width:100%;text-align:left}.dynamic-table table.table thead th .search-input{width:100%}.dynamic-table table.table thead th span{display:inline-block;vertical-align:top}.dynamic-table table.table thead th a{cursor:pointer;text-align:left}.dynamic-table table.table thead th.filter-column{text-align:center}.dynamic-table table.table thead tr:first-child th{border-top-width:0}.dynamic-table table.table tbody tr:last-child td{border-bottom-width:0}.dynamic-table table.table thead tr th,.dynamic-table table.table tbody tr td{background-color:var(--table-bg)}.dynamic-table table.table thead tr th:first-child,.dynamic-table table.table tbody tr td:first-child{border-left-width:0}.dynamic-table table.table thead tr th:last-child,.dynamic-table table.table tbody tr td:last-child{border-right-width:0}.dynamic-table table.table tbody tr.active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd) td{background-color:var(--table-stripe-bg)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd).active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link{margin-right:0;padding-right:0}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link:after{display:none}.sort-dropdown-content-wrapper a.sort,.dynamic-table a.sort{position:relative;display:block;margin-right:calc(var(--arrow-size) * 2);-webkit-user-select:none;user-select:none;padding-right:5px}.sort-dropdown-content-wrapper a.sort:before,.sort-dropdown-content-wrapper a.sort:after,.dynamic-table a.sort:before,.dynamic-table a.sort:after{content:\"\";position:absolute;transition:.2s ease;left:calc(100% + var(--arrow-size));top:calc(50% - var(--arrow-size));border-top:var(--arrow-size) solid transparent;border-bottom:var(--arrow-size) solid transparent;border-left:var(--arrow-size) solid var(--arrow-color);transform:rotate(calc(var(--arrow-rotation) * 1deg)) translate(var(--arrow-space))}.sort-dropdown-content-wrapper a.sort:before,.dynamic-table a.sort:before{--arrow-rotation: -90}.sort-dropdown-content-wrapper a.sort.sort-desc:before,.dynamic-table a.sort.sort-desc:before{--arrow-color: black}.sort-dropdown-content-wrapper a.sort.sort-asc:after,.dynamic-table a.sort.sort-asc:after{--arrow-color: black}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$3.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgxTemplateOutletDirective, selector: "[ngxTemplateOutlet]", inputs: ["context", "additionalContext", "ngxTemplateOutlet"] }, { kind: "directive", type: PaginationDirective, selector: "[pagination]", inputs: ["pagination", "page", "itemsPerPage", "updateTime", "waitFor"], outputs: ["pageChange", "onRefresh"], exportAs: ["pagination"] }, { kind: "directive", type: PaginationItemDirective, selector: "[paginationItem]" }, { kind: "component", type: DropdownBoxComponent, selector: "dropdown-box", inputs: ["closeInside", "attachTo", "placement", "crossAxis", "alignment", "autoAlignment", "allowedPlacements", "componentClass"] }, { kind: "component", type: PaginationMenuComponent, selector: "pagination-menu", inputs: ["maxSize", "urlParam", "directionLinks", "boundaryLinks"] }, { kind: "pipe", type: IncludesPipe, name: "includes" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: ValuesPipe, name: "values" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7491
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: DynamicTableComponent, isStandalone: false, selector: "dynamic-table", inputs: { dataLoader: "dataLoader", data: "data", selected: "selected", page: "page", urlParam: "urlParam", parallelData: "parallelData", columns: "columns", showFilter: "showFilter", filterLabel: "filterLabel", placeholder: "placeholder", showItems: "showItems", itemsPerPage: "itemsPerPage", updateTime: "updateTime", filterTime: "filterTime", maxPages: "maxPages", directionLinks: "directionLinks", boundaryLinks: "boundaryLinks", orderBy: "orderBy", orderDescending: "orderDescending", testId: "testId", titlePrefix: "titlePrefix", dragStartFn: "dragStartFn", dragEnterFn: "dragEnterFn", dropFn: "dropFn" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: ["rowTemplate"], descendants: true, static: true }, { propertyName: "wrapperTemplate", first: true, predicate: ["wrapperTemplate"], descendants: true, static: true }, { propertyName: "templateDirectives", predicate: DynamicTableTemplateDirective }], viewQueries: [{ propertyName: "columnsTemplate", first: true, predicate: ["columnsTemplate"], descendants: true, static: true }, { propertyName: "defaultRowTemplate", first: true, predicate: ["defaultRowTemplate"], descendants: true, static: true }, { propertyName: "defaultWrapperTemplate", first: true, predicate: ["defaultWrapperTemplate"], descendants: true, static: true }, { propertyName: "pagination", first: true, predicate: ["pagination"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-template #columnTemplate let-context let-column=\"column\" let-template=\"template\">\n <ng-template #defaultTemplate let-column=\"column\" let-item=\"item\">\n <span>{{ item[column] == undefined || item[column] == null ? '-' : item[column] }}</span>\n </ng-template>\n <ng-template #pureTemplate>\n <ng-container [ngxTemplateOutlet]=\"template.ref\" [context]=\"context\"></ng-container>\n </ng-template>\n <td [ngClass]=\"'column-' + column\"\n [attr.data-testid]=\"testId + '-' + column + '-' + context.rowIndex\"\n *ngIf=\"!template || !template.pure; else pureTemplate\">\n <ng-container [ngxTemplateOutlet]=\"!template ? defaultTemplate : template.ref\"\n [context]=\"context\"></ng-container>\n </td>\n</ng-template>\n\n<ng-template #columnsTemplate let-context>\n <ng-container *ngFor=\"let column of cols\"\n [ngxTemplateOutlet]=\"columnTemplate\"\n [context]=\"context\"\n [additionalContext]=\"{\n template: templates[column],\n column: column\n }\"></ng-container>\n</ng-template>\n\n<ng-template #defaultRowTemplate let-context>\n <tr #elem\n [draggable]=\"!!dragStartFn\"\n [ngClass]=\"{active: selected === context.item}\"\n (dragstart)=\"onDragStart($event, elem, context.item)\"\n (dragenter)=\"onDragEnter($event, elem, context.item)\"\n (dragleave)=\"onDragLeave($event, elem)\"\n (drop)=\"onDrop($event, elem, context.item)\">\n <ng-container [ngxTemplateOutlet]=\"columnsTemplate\" [context]=\"context\"></ng-container>\n </tr>\n</ng-template>\n\n<ng-template #headerTemplate let-column=\"column\" let-toggle=\"toggle\">\n <ng-template #defaultCol>\n <span>{{ realColumns[column].title | translate }}</span>\n </ng-template>\n <ng-template #emptyCol>\n <span>-</span>\n </ng-template>\n <ng-container *ngIf=\"realColumns[column]; else emptyCol\">\n <a *ngIf=\"realColumns[column].sort; else defaultCol\"\n [ngClass]=\"['sort', orderBy !== column ? '' : (orderDescending ? 'sort-desc' : 'sort-asc')]\"\n (click)=\"setSorting(column, toggle)\">\n <span>{{ realColumns[column].title | translate }}</span>\n </a>\n </ng-container>\n</ng-template>\n\n<div class=\"dynamic-table\">\n <div class=\"table-features-row\">\n <ng-content select=\"[table-features-before]\"></ng-content>\n @if (showFilter) {\n <div class=\"table-input-wrap table-search-filter\">\n <label *ngIf=\"filterLabel\" [attr.for]=\"tableId\">\n {{ filterLabel | translate }}\n </label>\n <input type=\"text\"\n class=\"search-input\"\n [attr.id]=\"tableId\"\n [attr.data-testid]=\"testId + '-filter-input'\"\n [placeholder]=\"placeholder | translate\"\n [ngModel]=\"filter\"\n (ngModelChange)=\"setFilter($event)\"/>\n </div>\n }\n @if (sortable) {\n <dropdown-box componentClass=\"sort-dropdown\" #sortDd>\n <ng-container toggle-content\n [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: orderBy, toggle: sortDd}\"></ng-container>\n <ul>\n <ng-container *ngFor=\"let column of cols\">\n <li [ngClass]=\"'sort-column sort-' + column\" *ngIf=\"realColumns[column].sort\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n }\n @if (showItems) {\n <div class=\"table-input-wrap table-items-count\">\n <label>\n {{ 'label.items.before' | translate }}\n </label>\n <dropdown-box>\n <ng-container toggle-content>\n {{ itemsPerPage }}\n </ng-container>\n <ul>\n <ng-container *ngFor=\"let count of showItems\">\n <li [ngClass]=\"'item-count count-' + count\" (click)=\"setItemsPerPage(count)\">\n {{ count }}\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <label>\n {{ 'label.items.after' | translate }}\n </label>\n </div>\n }\n <ng-content select=\"[table-features-after]\"></ng-content>\n </div>\n <div class=\"table-content-row\"\n #pagination=\"pagination\"\n [pagination]=\"loadData\"\n [page]=\"page\"\n [itemsPerPage]=\"itemsPerPage\"\n [updateTime]=\"updateTime\">\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n <div class=\"table-responsive\">\n <ng-template #defaultWrapperTemplate>\n <table class=\"table table-striped\">\n <thead>\n <tr>\n <th *ngFor=\"let column of cols\" [ngClass]=\"'header-column column-' + column\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </th>\n </tr>\n <tr *ngIf=\"hasQuery\">\n <th *ngFor=\"let column of cols\" [ngClass]=\"['column-' + column, 'filter-column']\">\n <ng-container *ngIf=\"realColumns[column].filter\" [ngSwitch]=\"realColumns[column].filterType\">\n <ng-container *ngSwitchCase=\"'enum'\">\n <ng-template #optionItem let-option=\"option\">\n {{ (realColumns[column].enumPrefix ? realColumns[column].enumPrefix + '.' + option : option) | translate }}\n </ng-template>\n <dropdown-box componentClass=\"filter-box\"\n [ngClass]=\"'filter-box-' + column\" [closeInside]=\"false\">\n <ng-container toggle-content>\n <span class=\"toggle-placeholder\" *ngIf=\"!query[column]\">\n {{ realColumns[column].title | translate }}\n </span>\n <span [ngClass]=\"['option-' + option, column + '-option-' + option, option]\"\n *ngFor=\"let option of query[column] | values; let ix = index\">\n <ng-container *ngIf=\"ix > 0\">, </ng-container>\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </span>\n </ng-container>\n <ul>\n <li [ngClass]=\"[column + '-option', 'option-' + option, option]\"\n (click)=\"setQueryValue(column, option)\"\n *ngFor=\"let option of realColumns[column].enum\">\n <a [ngClass]=\"'toggle-link-' + column\">\n <input type=\"checkbox\" [checked]=\"query[column] | includes: option\">\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </a>\n </li>\n </ul>\n </dropdown-box>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input type=\"checkbox\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <input class=\"search-input\"\n type=\"text\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n </ng-container>\n </th>\n </tr>\n </thead>\n <tbody>\n <ng-container *paginationItem=\"let context\"\n [ngxTemplateOutlet]=\"rowTemplate\"\n [context]=\"context\"\n [additionalContext]=\"this\"></ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <div class=\"table-wrapper\">\n <ng-content select=\"[table-top]\"></ng-content>\n <ng-container [ngxTemplateOutlet]=\"wrapperTemplate || defaultWrapperTemplate\"\n [context]=\"this\"></ng-container>\n <ng-content select=\"[table-bottom]\"></ng-content>\n </div>\n </div>\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n </div>\n</div>\n", styles: [".dynamic-table{--table-bg: transparent;--table-stripe-bg: rgba(210, 210, 210, .35);--border-size: 1px;--border-color: #ced4da;--bg-color: #ffffff;--text-color: #151515;--highlight-color: var(--primary-color, #888888);--highlight-text-color: #ffffff;--display-toggle: none;--arrow-size: 6px;--arrow-rotation: 90;--arrow-space: calc(var(--arrow-size) * .5 + 1px);--arrow-color: #c6c6c6}.dynamic-table *{box-sizing:border-box}.dynamic-table .search-input{background:var(--bg-color);color:var(--text-color);border:var(--border-size) solid var(--border-color);border-radius:5px;padding:6px 12px;-webkit-user-select:none;user-select:none;font-weight:400;font-size:var(--table-input-font-size, 15px);line-height:var(--table-input-line-height, 18px);outline:none}.dynamic-table .search-input .toggle-placeholder,.dynamic-table .search-input ::placeholder{color:#495057}.dynamic-table .table-responsive{border:1px solid var(--border-color);overflow:hidden;overflow-x:auto;margin-bottom:1rem}.dynamic-table .table-features-row:not(:empty){display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:20px}.dynamic-table .table-content-row{position:relative}.dynamic-table .sort-dropdown{display:none}.dynamic-table .table-input-wrap{display:flex;align-items:center;justify-content:flex-end;gap:5px}.dynamic-table .table-input-wrap>label{margin:0;font-weight:700}.dynamic-table .table-input-wrap>input{max-width:400px}.dynamic-table .table-items-count{flex:1}.dynamic-table .table-wrapper{position:relative}.dynamic-table table.table{border-collapse:collapse;margin:0;width:100%;font-family:inherit;font-size:inherit}.dynamic-table table.table th{text-align:left}.dynamic-table table.table th,.dynamic-table table.table td{text-align:left;padding:6px 12px;border:1px solid var(--border-color);vertical-align:middle;white-space:nowrap;width:var(--cell-width, 25%);min-width:fit-content}.dynamic-table table.table-sm th,.dynamic-table table.table-sm td{font-size:var(--font-size-sm);padding:4px 6px}.dynamic-table table.table thead th{font-weight:500}.dynamic-table table.table thead th .dropdown-box{display:block;width:100%;text-align:left}.dynamic-table table.table thead th .search-input{width:100%}.dynamic-table table.table thead th span{display:inline-block;vertical-align:top}.dynamic-table table.table thead th a{cursor:pointer;text-align:left}.dynamic-table table.table thead th.filter-column{text-align:center}.dynamic-table table.table thead tr:first-child th{border-top-width:0}.dynamic-table table.table tbody tr:last-child td{border-bottom-width:0}.dynamic-table table.table thead tr th,.dynamic-table table.table tbody tr td{background-color:var(--table-bg)}.dynamic-table table.table thead tr th:first-child,.dynamic-table table.table tbody tr td:first-child{border-left-width:0}.dynamic-table table.table thead tr th:last-child,.dynamic-table table.table tbody tr td:last-child{border-right-width:0}.dynamic-table table.table tbody tr.active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd) td{background-color:var(--table-stripe-bg)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd).active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link{margin-right:0;padding-right:0}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link:after{display:none}.sort-dropdown-content-wrapper a.sort,.dynamic-table a.sort{position:relative;display:block;margin-right:calc(var(--arrow-size) * 2);-webkit-user-select:none;user-select:none;padding-right:5px}.sort-dropdown-content-wrapper a.sort:before,.sort-dropdown-content-wrapper a.sort:after,.dynamic-table a.sort:before,.dynamic-table a.sort:after{content:\"\";position:absolute;transition:.2s ease;left:calc(100% + var(--arrow-size));top:calc(50% - var(--arrow-size));border-top:var(--arrow-size) solid transparent;border-bottom:var(--arrow-size) solid transparent;border-left:var(--arrow-size) solid var(--arrow-color);transform:rotate(calc(var(--arrow-rotation) * 1deg)) translate(var(--arrow-space))}.sort-dropdown-content-wrapper a.sort:before,.dynamic-table a.sort:before{--arrow-rotation: -90}.sort-dropdown-content-wrapper a.sort.sort-desc:before,.dynamic-table a.sort.sort-desc:before{--arrow-color: black}.sort-dropdown-content-wrapper a.sort.sort-asc:after,.dynamic-table a.sort.sort-asc:after{--arrow-color: black}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$3.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i2$1.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: i2$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgxTemplateOutletDirective, selector: "[ngxTemplateOutlet]", inputs: ["context", "additionalContext", "ngxTemplateOutlet"] }, { kind: "directive", type: PaginationDirective, selector: "[pagination]", inputs: ["pagination", "page", "itemsPerPage", "updateTime", "waitFor"], outputs: ["pageChange", "onRefresh"], exportAs: ["pagination"] }, { kind: "directive", type: PaginationItemDirective, selector: "[paginationItem]" }, { kind: "component", type: DropdownBoxComponent, selector: "dropdown-box", inputs: ["closeInside", "attachTo", "placement", "crossAxis", "alignment", "autoAlignment", "allowedPlacements", "componentClass"] }, { kind: "component", type: PaginationMenuComponent, selector: "pagination-menu", inputs: ["maxSize", "urlParam", "directionLinks", "boundaryLinks"] }, { kind: "pipe", type: IncludesPipe, name: "includes" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: ValuesPipe, name: "values" }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
7478
7492
|
}
|
|
7479
7493
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
|
7480
7494
|
type: Component,
|
|
7481
|
-
args: [{ standalone: false, encapsulation: ViewEncapsulation.None, selector: "dynamic-table", template: "<ng-template #columnTemplate let-context let-column=\"column\" let-template=\"template\">\n <ng-template #defaultTemplate let-column=\"column\" let-item=\"item\">\n <span>{{ item[column] == undefined || item[column] == null ? '-' : item[column] }}</span>\n </ng-template>\n <ng-template #pureTemplate>\n <ng-container [ngxTemplateOutlet]=\"template.ref\" [context]=\"context\"></ng-container>\n </ng-template>\n <td [ngClass]=\"'column-' + column\"\n [attr.data-testid]=\"testId + '-' + column + '-' + context.rowIndex\"\n *ngIf=\"!template || !template.pure; else pureTemplate\">\n <ng-container [ngxTemplateOutlet]=\"!template ? defaultTemplate : template.ref\"\n [context]=\"context\"></ng-container>\n </td>\n</ng-template>\n\n<ng-template #columnsTemplate let-context>\n <ng-container *ngFor=\"let column of cols\"\n [ngxTemplateOutlet]=\"columnTemplate\"\n [context]=\"context\"\n [additionalContext]=\"{\n template: templates[column],\n column: column\n }\"></ng-container>\n</ng-template>\n\n<ng-template #defaultRowTemplate let-context>\n <tr #elem\n [draggable]=\"!!dragStartFn\"\n [ngClass]=\"{active: selected === context.item}\"\n (dragstart)=\"onDragStart($event, elem, context.item)\"\n (dragenter)=\"onDragEnter($event, elem, context.item)\"\n (dragleave)=\"onDragLeave($event, elem)\"\n (drop)=\"onDrop($event, elem, context.item)\">\n <ng-container [ngxTemplateOutlet]=\"columnsTemplate\" [context]=\"context\"></ng-container>\n </tr>\n</ng-template>\n\n<ng-template #headerTemplate let-column=\"column\" let-toggle=\"toggle\">\n <ng-template #defaultCol>\n <span>{{ realColumns[column].title | translate }}</span>\n </ng-template>\n <ng-template #emptyCol>\n <span>-</span>\n </ng-template>\n <ng-container *ngIf=\"realColumns[column]; else emptyCol\">\n <a *ngIf=\"realColumns[column].sort; else defaultCol\"\n [ngClass]=\"['sort', orderBy !== column ? '' : (orderDescending ? 'sort-desc' : 'sort-asc')]\"\n (click)=\"setSorting(column, toggle)\">\n <span>{{ realColumns[column].title | translate }}</span>\n </a>\n </ng-container>\n</ng-template>\n\n<div class=\"dynamic-table\">\n <div class=\"table-features-row\">\n <ng-content select=\"[table-features-before]\"></ng-content>\n <div class=\"table-input-wrap table-search-filter\" *ngIf=\"showFilter\">\n <label *ngIf=\"filterLabel\" [attr.for]=\"tableId\">\n {{ filterLabel | translate }}\n </label>\n <input type=\"text\"\n class=\"search-input\"\n [attr.id]=\"tableId\"\n [attr.data-testid]=\"testId + '-filter-input'\"\n [placeholder]=\"placeholder | translate\"\n [ngModel]=\"filter\"\n (ngModelChange)=\"setFilter($event)\"/>\n </div>\n <dropdown-box componentClass=\"sort-dropdown\" #sortDd>\n <ng-container toggle-content\n [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: orderBy, toggle: sortDd}\"></ng-container>\n <ul>\n <ng-container *ngFor=\"let column of cols\">\n <li [ngClass]=\"'sort-column sort-' + column\" *ngIf=\"realColumns[column].sort\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <div class=\"table-input-wrap table-items-count\" *ngIf=\"showItems\">\n <label>\n {{ 'label.items.before' | translate }}\n </label>\n <dropdown-box>\n <ng-container toggle-content>\n {{ itemsPerPage }}\n </ng-container>\n <ul>\n <ng-container *ngFor=\"let count of showItems\">\n <li [ngClass]=\"'item-count count-' + count\" (click)=\"setItemsPerPage(count)\">\n {{ count }}\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <label>\n {{ 'label.items.after' | translate }}\n </label>\n </div>\n <ng-content select=\"[table-features-after]\"></ng-content>\n </div>\n <div class=\"table-content-row\"\n #pagination=\"pagination\"\n [pagination]=\"loadData\"\n [page]=\"page\"\n [itemsPerPage]=\"itemsPerPage\"\n [updateTime]=\"updateTime\">\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n <div class=\"table-responsive\">\n <ng-template #defaultWrapperTemplate>\n <table class=\"table table-striped\">\n <thead>\n <tr>\n <th *ngFor=\"let column of cols\" [ngClass]=\"'header-column column-' + column\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </th>\n </tr>\n <tr *ngIf=\"hasQuery\">\n <th *ngFor=\"let column of cols\" [ngClass]=\"['column-' + column, 'filter-column']\">\n <ng-container *ngIf=\"realColumns[column].filter\" [ngSwitch]=\"realColumns[column].filterType\">\n <ng-container *ngSwitchCase=\"'enum'\">\n <ng-template #optionItem let-option=\"option\">\n {{ (realColumns[column].enumPrefix ? realColumns[column].enumPrefix + '.' + option : option) | translate }}\n </ng-template>\n <dropdown-box componentClass=\"filter-box\"\n [ngClass]=\"'filter-box-' + column\" [closeInside]=\"false\">\n <ng-container toggle-content>\n <span class=\"toggle-placeholder\" *ngIf=\"!query[column]\">\n {{ realColumns[column].title | translate }}\n </span>\n <span [ngClass]=\"['option-' + option, column + '-option-' + option, option]\"\n *ngFor=\"let option of query[column] | values; let ix = index\">\n <ng-container *ngIf=\"ix > 0\">, </ng-container>\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </span>\n </ng-container>\n <ul>\n <li [ngClass]=\"[column + '-option', 'option-' + option, option]\"\n (click)=\"setQueryValue(column, option)\"\n *ngFor=\"let option of realColumns[column].enum\">\n <a [ngClass]=\"'toggle-link-' + column\">\n <input type=\"checkbox\" [checked]=\"query[column] | includes: option\">\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </a>\n </li>\n </ul>\n </dropdown-box>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input type=\"checkbox\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <input class=\"search-input\"\n type=\"text\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n </ng-container>\n </th>\n </tr>\n </thead>\n <tbody>\n <ng-container *paginationItem=\"let context\"\n [ngxTemplateOutlet]=\"rowTemplate\"\n [context]=\"context\"\n [additionalContext]=\"this\"></ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <div class=\"table-wrapper\">\n <ng-content select=\"[table-top]\"></ng-content>\n <ng-container [ngxTemplateOutlet]=\"wrapperTemplate || defaultWrapperTemplate\"\n [context]=\"this\"></ng-container>\n <ng-content select=\"[table-bottom]\"></ng-content>\n </div>\n </div>\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n </div>\n</div>\n", styles: [".dynamic-table{--table-bg: transparent;--table-stripe-bg: rgba(210, 210, 210, .35);--border-size: 1px;--border-color: #ced4da;--bg-color: #ffffff;--text-color: #151515;--highlight-color: var(--primary-color, #888888);--highlight-text-color: #ffffff;--display-toggle: none;--arrow-size: 6px;--arrow-rotation: 90;--arrow-space: calc(var(--arrow-size) * .5 + 1px);--arrow-color: #c6c6c6}.dynamic-table *{box-sizing:border-box}.dynamic-table .search-input{background:var(--bg-color);color:var(--text-color);border:var(--border-size) solid var(--border-color);border-radius:5px;padding:6px 12px;-webkit-user-select:none;user-select:none;font-weight:400;font-size:var(--table-input-font-size, 15px);line-height:var(--table-input-line-height, 18px);outline:none}.dynamic-table .search-input .toggle-placeholder,.dynamic-table .search-input ::placeholder{color:#495057}.dynamic-table .table-responsive{border:1px solid var(--border-color);overflow:hidden;overflow-x:auto;margin-bottom:1rem}.dynamic-table .table-features-row:not(:empty){display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:20px}.dynamic-table .table-content-row{position:relative}.dynamic-table .sort-dropdown{display:none}.dynamic-table .table-input-wrap{display:flex;align-items:center;justify-content:flex-end;gap:5px}.dynamic-table .table-input-wrap>label{margin:0;font-weight:700}.dynamic-table .table-input-wrap>input{max-width:400px}.dynamic-table .table-items-count{flex:1}.dynamic-table .table-wrapper{position:relative}.dynamic-table table.table{border-collapse:collapse;margin:0;width:100%;font-family:inherit;font-size:inherit}.dynamic-table table.table th{text-align:left}.dynamic-table table.table th,.dynamic-table table.table td{text-align:left;padding:6px 12px;border:1px solid var(--border-color);vertical-align:middle;white-space:nowrap;width:var(--cell-width, 25%);min-width:fit-content}.dynamic-table table.table-sm th,.dynamic-table table.table-sm td{font-size:var(--font-size-sm);padding:4px 6px}.dynamic-table table.table thead th{font-weight:500}.dynamic-table table.table thead th .dropdown-box{display:block;width:100%;text-align:left}.dynamic-table table.table thead th .search-input{width:100%}.dynamic-table table.table thead th span{display:inline-block;vertical-align:top}.dynamic-table table.table thead th a{cursor:pointer;text-align:left}.dynamic-table table.table thead th.filter-column{text-align:center}.dynamic-table table.table thead tr:first-child th{border-top-width:0}.dynamic-table table.table tbody tr:last-child td{border-bottom-width:0}.dynamic-table table.table thead tr th,.dynamic-table table.table tbody tr td{background-color:var(--table-bg)}.dynamic-table table.table thead tr th:first-child,.dynamic-table table.table tbody tr td:first-child{border-left-width:0}.dynamic-table table.table thead tr th:last-child,.dynamic-table table.table tbody tr td:last-child{border-right-width:0}.dynamic-table table.table tbody tr.active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd) td{background-color:var(--table-stripe-bg)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd).active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link{margin-right:0;padding-right:0}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link:after{display:none}.sort-dropdown-content-wrapper a.sort,.dynamic-table a.sort{position:relative;display:block;margin-right:calc(var(--arrow-size) * 2);-webkit-user-select:none;user-select:none;padding-right:5px}.sort-dropdown-content-wrapper a.sort:before,.sort-dropdown-content-wrapper a.sort:after,.dynamic-table a.sort:before,.dynamic-table a.sort:after{content:\"\";position:absolute;transition:.2s ease;left:calc(100% + var(--arrow-size));top:calc(50% - var(--arrow-size));border-top:var(--arrow-size) solid transparent;border-bottom:var(--arrow-size) solid transparent;border-left:var(--arrow-size) solid var(--arrow-color);transform:rotate(calc(var(--arrow-rotation) * 1deg)) translate(var(--arrow-space))}.sort-dropdown-content-wrapper a.sort:before,.dynamic-table a.sort:before{--arrow-rotation: -90}.sort-dropdown-content-wrapper a.sort.sort-desc:before,.dynamic-table a.sort.sort-desc:before{--arrow-color: black}.sort-dropdown-content-wrapper a.sort.sort-asc:after,.dynamic-table a.sort.sort-asc:after{--arrow-color: black}\n"] }]
|
|
7495
|
+
args: [{ standalone: false, encapsulation: ViewEncapsulation.None, selector: "dynamic-table", template: "<ng-template #columnTemplate let-context let-column=\"column\" let-template=\"template\">\n <ng-template #defaultTemplate let-column=\"column\" let-item=\"item\">\n <span>{{ item[column] == undefined || item[column] == null ? '-' : item[column] }}</span>\n </ng-template>\n <ng-template #pureTemplate>\n <ng-container [ngxTemplateOutlet]=\"template.ref\" [context]=\"context\"></ng-container>\n </ng-template>\n <td [ngClass]=\"'column-' + column\"\n [attr.data-testid]=\"testId + '-' + column + '-' + context.rowIndex\"\n *ngIf=\"!template || !template.pure; else pureTemplate\">\n <ng-container [ngxTemplateOutlet]=\"!template ? defaultTemplate : template.ref\"\n [context]=\"context\"></ng-container>\n </td>\n</ng-template>\n\n<ng-template #columnsTemplate let-context>\n <ng-container *ngFor=\"let column of cols\"\n [ngxTemplateOutlet]=\"columnTemplate\"\n [context]=\"context\"\n [additionalContext]=\"{\n template: templates[column],\n column: column\n }\"></ng-container>\n</ng-template>\n\n<ng-template #defaultRowTemplate let-context>\n <tr #elem\n [draggable]=\"!!dragStartFn\"\n [ngClass]=\"{active: selected === context.item}\"\n (dragstart)=\"onDragStart($event, elem, context.item)\"\n (dragenter)=\"onDragEnter($event, elem, context.item)\"\n (dragleave)=\"onDragLeave($event, elem)\"\n (drop)=\"onDrop($event, elem, context.item)\">\n <ng-container [ngxTemplateOutlet]=\"columnsTemplate\" [context]=\"context\"></ng-container>\n </tr>\n</ng-template>\n\n<ng-template #headerTemplate let-column=\"column\" let-toggle=\"toggle\">\n <ng-template #defaultCol>\n <span>{{ realColumns[column].title | translate }}</span>\n </ng-template>\n <ng-template #emptyCol>\n <span>-</span>\n </ng-template>\n <ng-container *ngIf=\"realColumns[column]; else emptyCol\">\n <a *ngIf=\"realColumns[column].sort; else defaultCol\"\n [ngClass]=\"['sort', orderBy !== column ? '' : (orderDescending ? 'sort-desc' : 'sort-asc')]\"\n (click)=\"setSorting(column, toggle)\">\n <span>{{ realColumns[column].title | translate }}</span>\n </a>\n </ng-container>\n</ng-template>\n\n<div class=\"dynamic-table\">\n <div class=\"table-features-row\">\n <ng-content select=\"[table-features-before]\"></ng-content>\n @if (showFilter) {\n <div class=\"table-input-wrap table-search-filter\">\n <label *ngIf=\"filterLabel\" [attr.for]=\"tableId\">\n {{ filterLabel | translate }}\n </label>\n <input type=\"text\"\n class=\"search-input\"\n [attr.id]=\"tableId\"\n [attr.data-testid]=\"testId + '-filter-input'\"\n [placeholder]=\"placeholder | translate\"\n [ngModel]=\"filter\"\n (ngModelChange)=\"setFilter($event)\"/>\n </div>\n }\n @if (sortable) {\n <dropdown-box componentClass=\"sort-dropdown\" #sortDd>\n <ng-container toggle-content\n [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: orderBy, toggle: sortDd}\"></ng-container>\n <ul>\n <ng-container *ngFor=\"let column of cols\">\n <li [ngClass]=\"'sort-column sort-' + column\" *ngIf=\"realColumns[column].sort\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n }\n @if (showItems) {\n <div class=\"table-input-wrap table-items-count\">\n <label>\n {{ 'label.items.before' | translate }}\n </label>\n <dropdown-box>\n <ng-container toggle-content>\n {{ itemsPerPage }}\n </ng-container>\n <ul>\n <ng-container *ngFor=\"let count of showItems\">\n <li [ngClass]=\"'item-count count-' + count\" (click)=\"setItemsPerPage(count)\">\n {{ count }}\n </li>\n </ng-container>\n </ul>\n </dropdown-box>\n <label>\n {{ 'label.items.after' | translate }}\n </label>\n </div>\n }\n <ng-content select=\"[table-features-after]\"></ng-content>\n </div>\n <div class=\"table-content-row\"\n #pagination=\"pagination\"\n [pagination]=\"loadData\"\n [page]=\"page\"\n [itemsPerPage]=\"itemsPerPage\"\n [updateTime]=\"updateTime\">\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n <div class=\"table-responsive\">\n <ng-template #defaultWrapperTemplate>\n <table class=\"table table-striped\">\n <thead>\n <tr>\n <th *ngFor=\"let column of cols\" [ngClass]=\"'header-column column-' + column\">\n <ng-container [ngTemplateOutlet]=\"headerTemplate\"\n [ngTemplateOutletContext]=\"{column: column}\"></ng-container>\n </th>\n </tr>\n <tr *ngIf=\"hasQuery\">\n <th *ngFor=\"let column of cols\" [ngClass]=\"['column-' + column, 'filter-column']\">\n <ng-container *ngIf=\"realColumns[column].filter\" [ngSwitch]=\"realColumns[column].filterType\">\n <ng-container *ngSwitchCase=\"'enum'\">\n <ng-template #optionItem let-option=\"option\">\n {{ (realColumns[column].enumPrefix ? realColumns[column].enumPrefix + '.' + option : option) | translate }}\n </ng-template>\n <dropdown-box componentClass=\"filter-box\"\n [ngClass]=\"'filter-box-' + column\" [closeInside]=\"false\">\n <ng-container toggle-content>\n <span class=\"toggle-placeholder\" *ngIf=\"!query[column]\">\n {{ realColumns[column].title | translate }}\n </span>\n <span [ngClass]=\"['option-' + option, column + '-option-' + option, option]\"\n *ngFor=\"let option of query[column] | values; let ix = index\">\n <ng-container *ngIf=\"ix > 0\">, </ng-container>\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </span>\n </ng-container>\n <ul>\n <li [ngClass]=\"[column + '-option', 'option-' + option, option]\"\n (click)=\"setQueryValue(column, option)\"\n *ngFor=\"let option of realColumns[column].enum\">\n <a [ngClass]=\"'toggle-link-' + column\">\n <input type=\"checkbox\" [checked]=\"query[column] | includes: option\">\n <ng-container [ngTemplateOutlet]=\"optionItem\"\n [ngTemplateOutletContext]=\"{option: option}\"></ng-container>\n </a>\n </li>\n </ul>\n </dropdown-box>\n </ng-container>\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <input type=\"checkbox\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <input class=\"search-input\"\n type=\"text\"\n [attr.data-testid]=\"testId + '-filter-' + column\"\n [placeholder]=\"realColumns[column].title | translate\"\n [ngModel]=\"query[column]\"\n (ngModelChange)=\"setQueryValue(column, $event)\"/>\n </ng-container>\n </ng-container>\n </th>\n </tr>\n </thead>\n <tbody>\n <ng-container *paginationItem=\"let context\"\n [ngxTemplateOutlet]=\"rowTemplate\"\n [context]=\"context\"\n [additionalContext]=\"this\"></ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <div class=\"table-wrapper\">\n <ng-content select=\"[table-top]\"></ng-content>\n <ng-container [ngxTemplateOutlet]=\"wrapperTemplate || defaultWrapperTemplate\"\n [context]=\"this\"></ng-container>\n <ng-content select=\"[table-bottom]\"></ng-content>\n </div>\n </div>\n <pagination-menu [urlParam]=\"urlParam\" [maxSize]=\"maxPages\" [directionLinks]=\"directionLinks\"\n [boundaryLinks]=\"boundaryLinks\"></pagination-menu>\n </div>\n</div>\n", styles: [".dynamic-table{--table-bg: transparent;--table-stripe-bg: rgba(210, 210, 210, .35);--border-size: 1px;--border-color: #ced4da;--bg-color: #ffffff;--text-color: #151515;--highlight-color: var(--primary-color, #888888);--highlight-text-color: #ffffff;--display-toggle: none;--arrow-size: 6px;--arrow-rotation: 90;--arrow-space: calc(var(--arrow-size) * .5 + 1px);--arrow-color: #c6c6c6}.dynamic-table *{box-sizing:border-box}.dynamic-table .search-input{background:var(--bg-color);color:var(--text-color);border:var(--border-size) solid var(--border-color);border-radius:5px;padding:6px 12px;-webkit-user-select:none;user-select:none;font-weight:400;font-size:var(--table-input-font-size, 15px);line-height:var(--table-input-line-height, 18px);outline:none}.dynamic-table .search-input .toggle-placeholder,.dynamic-table .search-input ::placeholder{color:#495057}.dynamic-table .table-responsive{border:1px solid var(--border-color);overflow:hidden;overflow-x:auto;margin-bottom:1rem}.dynamic-table .table-features-row:not(:empty){display:flex;gap:10px;flex-wrap:wrap;align-items:center;justify-content:space-between;margin-bottom:20px}.dynamic-table .table-content-row{position:relative}.dynamic-table .sort-dropdown{display:none}.dynamic-table .table-input-wrap{display:flex;align-items:center;justify-content:flex-end;gap:5px}.dynamic-table .table-input-wrap>label{margin:0;font-weight:700}.dynamic-table .table-input-wrap>input{max-width:400px}.dynamic-table .table-items-count{flex:1}.dynamic-table .table-wrapper{position:relative}.dynamic-table table.table{border-collapse:collapse;margin:0;width:100%;font-family:inherit;font-size:inherit}.dynamic-table table.table th{text-align:left}.dynamic-table table.table th,.dynamic-table table.table td{text-align:left;padding:6px 12px;border:1px solid var(--border-color);vertical-align:middle;white-space:nowrap;width:var(--cell-width, 25%);min-width:fit-content}.dynamic-table table.table-sm th,.dynamic-table table.table-sm td{font-size:var(--font-size-sm);padding:4px 6px}.dynamic-table table.table thead th{font-weight:500}.dynamic-table table.table thead th .dropdown-box{display:block;width:100%;text-align:left}.dynamic-table table.table thead th .search-input{width:100%}.dynamic-table table.table thead th span{display:inline-block;vertical-align:top}.dynamic-table table.table thead th a{cursor:pointer;text-align:left}.dynamic-table table.table thead th.filter-column{text-align:center}.dynamic-table table.table thead tr:first-child th{border-top-width:0}.dynamic-table table.table tbody tr:last-child td{border-bottom-width:0}.dynamic-table table.table thead tr th,.dynamic-table table.table tbody tr td{background-color:var(--table-bg)}.dynamic-table table.table thead tr th:first-child,.dynamic-table table.table tbody tr td:first-child{border-left-width:0}.dynamic-table table.table thead tr th:last-child,.dynamic-table table.table tbody tr td:last-child{border-right-width:0}.dynamic-table table.table tbody tr.active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd) td{background-color:var(--table-stripe-bg)}.dynamic-table .table-striped>tbody>tr:nth-of-type(odd).active td{background-color:var(--highlight-color);color:var(--highlight-text-color)}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link{margin-right:0;padding-right:0}.sort-dropdown .dropdown-box-toggle a.dropdown-box-toggle-link:after{display:none}.sort-dropdown-content-wrapper a.sort,.dynamic-table a.sort{position:relative;display:block;margin-right:calc(var(--arrow-size) * 2);-webkit-user-select:none;user-select:none;padding-right:5px}.sort-dropdown-content-wrapper a.sort:before,.sort-dropdown-content-wrapper a.sort:after,.dynamic-table a.sort:before,.dynamic-table a.sort:after{content:\"\";position:absolute;transition:.2s ease;left:calc(100% + var(--arrow-size));top:calc(50% - var(--arrow-size));border-top:var(--arrow-size) solid transparent;border-bottom:var(--arrow-size) solid transparent;border-left:var(--arrow-size) solid var(--arrow-color);transform:rotate(calc(var(--arrow-rotation) * 1deg)) translate(var(--arrow-space))}.sort-dropdown-content-wrapper a.sort:before,.dynamic-table a.sort:before{--arrow-rotation: -90}.sort-dropdown-content-wrapper a.sort.sort-desc:before,.dynamic-table a.sort.sort-desc:before{--arrow-color: black}.sort-dropdown-content-wrapper a.sort.sort-asc:after,.dynamic-table a.sort.sort-asc:after{--arrow-color: black}\n"] }]
|
|
7482
7496
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { dataLoader: [{
|
|
7483
7497
|
type: Input
|
|
7484
7498
|
}], data: [{
|
|
@@ -7582,6 +7596,14 @@ class InteractiveItemComponent {
|
|
|
7582
7596
|
get shapes() {
|
|
7583
7597
|
return this.mShapes;
|
|
7584
7598
|
}
|
|
7599
|
+
get hovered() {
|
|
7600
|
+
return this.canvas?.hoveredItem === this;
|
|
7601
|
+
}
|
|
7602
|
+
set hovered(value) {
|
|
7603
|
+
if (!this.canvas)
|
|
7604
|
+
return;
|
|
7605
|
+
this.canvas.hoveredItem = value ? this : null;
|
|
7606
|
+
}
|
|
7585
7607
|
get x() {
|
|
7586
7608
|
return this.pos.x;
|
|
7587
7609
|
}
|
|
@@ -7625,7 +7647,6 @@ class InteractiveItemComponent {
|
|
|
7625
7647
|
this.active = false;
|
|
7626
7648
|
this.index = -1;
|
|
7627
7649
|
this.valid = true;
|
|
7628
|
-
this.cycles = [0];
|
|
7629
7650
|
this.pos = Point.Zero;
|
|
7630
7651
|
this.direction = "none";
|
|
7631
7652
|
this.mShapes = [];
|
|
@@ -7640,14 +7661,11 @@ class InteractiveItemComponent {
|
|
|
7640
7661
|
return;
|
|
7641
7662
|
this.calcShapes();
|
|
7642
7663
|
}
|
|
7643
|
-
calcShapes(
|
|
7664
|
+
calcShapes() {
|
|
7644
7665
|
const ratio = this.canvas.ratio ?? 1;
|
|
7645
7666
|
const x = this.pos.x * ratio;
|
|
7646
|
-
|
|
7647
|
-
this.mShapes = this.cycles.map(pan =>
|
|
7648
|
-
const y = this.pos.y * ratio + pan;
|
|
7649
|
-
return this.calcShape(x, y);
|
|
7650
|
-
});
|
|
7667
|
+
const y = this.pos.y * ratio;
|
|
7668
|
+
this.mShapes = this.canvas.cycles.map(pan => this.calcShape(x, y + pan));
|
|
7651
7669
|
}
|
|
7652
7670
|
hit(point) {
|
|
7653
7671
|
for (const shape of this.shapes) {
|
|
@@ -7656,7 +7674,7 @@ class InteractiveItemComponent {
|
|
|
7656
7674
|
}
|
|
7657
7675
|
return false;
|
|
7658
7676
|
}
|
|
7659
|
-
|
|
7677
|
+
moveBy(dx, dy) {
|
|
7660
7678
|
if (this.direction === "none")
|
|
7661
7679
|
return;
|
|
7662
7680
|
switch (this.direction) {
|
|
@@ -7670,7 +7688,6 @@ class InteractiveItemComponent {
|
|
|
7670
7688
|
this.pos = new Point(this.pos.x + dx, this.pos.y + dy);
|
|
7671
7689
|
break;
|
|
7672
7690
|
}
|
|
7673
|
-
const params = this.canvas.params || {};
|
|
7674
7691
|
this.calcShapes();
|
|
7675
7692
|
this.valid = this.isValidByParams() && this.canvas.items.every(other => this === other || this.isValidByDistance(other));
|
|
7676
7693
|
this.validPos = this.valid ? this.pos : this.validPos;
|
|
@@ -7686,14 +7703,16 @@ class InteractiveItemComponent {
|
|
|
7686
7703
|
return true;
|
|
7687
7704
|
}
|
|
7688
7705
|
isValidByDistance(other) {
|
|
7689
|
-
const
|
|
7690
|
-
const minPixels = isNaN(min) || min <= 0 ? 1 : min * this.canvas.ratio;
|
|
7706
|
+
const minPixels = this.distToPixels(this.getMinDistance(other));
|
|
7691
7707
|
return !this.shapes.some(shape => {
|
|
7692
7708
|
return other.shapes.some(os => {
|
|
7693
7709
|
return os.minDistance(shape) <= minPixels;
|
|
7694
7710
|
});
|
|
7695
7711
|
});
|
|
7696
7712
|
}
|
|
7713
|
+
distToPixels(value) {
|
|
7714
|
+
return !this.canvas ? 1 : Math.max(1, (isNaN(value) || value < 0 ? 0 : value) * (this.canvas.ratio ?? 1));
|
|
7715
|
+
}
|
|
7697
7716
|
getMinDistance(other) {
|
|
7698
7717
|
return !other ? 0 : null;
|
|
7699
7718
|
}
|
|
@@ -7724,19 +7743,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
7724
7743
|
|
|
7725
7744
|
class InteractiveCanvasComponent {
|
|
7726
7745
|
get items() {
|
|
7727
|
-
return this.
|
|
7746
|
+
return this.$items.value;
|
|
7728
7747
|
}
|
|
7729
7748
|
get canvas() {
|
|
7730
7749
|
return this.canvasElem?.nativeElement;
|
|
7731
7750
|
}
|
|
7732
7751
|
get lockedItem() {
|
|
7733
|
-
return this.
|
|
7752
|
+
return this.items[this.lockedIndex];
|
|
7734
7753
|
}
|
|
7735
7754
|
get selectedItem() {
|
|
7736
|
-
return this.
|
|
7755
|
+
return this.items[this.selectedIndex];
|
|
7737
7756
|
}
|
|
7738
7757
|
get hoveredItem() {
|
|
7739
|
-
return this.
|
|
7758
|
+
return this.items[this.hoveredIndex];
|
|
7759
|
+
}
|
|
7760
|
+
set hoveredItem(item) {
|
|
7761
|
+
this.hoveredIndex = !item ? -1 : this.items.indexOf(item);
|
|
7740
7762
|
}
|
|
7741
7763
|
constructor(renderer, universal, element, rootElement) {
|
|
7742
7764
|
this.renderer = renderer;
|
|
@@ -7751,16 +7773,21 @@ class InteractiveCanvasComponent {
|
|
|
7751
7773
|
this.realHeight = 100;
|
|
7752
7774
|
this.panOffset = 0;
|
|
7753
7775
|
this.params = {};
|
|
7776
|
+
this.beforeItems = [];
|
|
7777
|
+
this.afterItems = [];
|
|
7754
7778
|
this.selectedIndexChange = new EventEmitter();
|
|
7755
|
-
this.
|
|
7756
|
-
this.
|
|
7779
|
+
this.onRotate = new EventEmitter();
|
|
7780
|
+
this.onItemPan = new EventEmitter();
|
|
7781
|
+
this.onItemPanned = new EventEmitter();
|
|
7782
|
+
this.onPan = new EventEmitter();
|
|
7783
|
+
this.onPanned = new EventEmitter();
|
|
7784
|
+
this.$items = new BehaviorSubject([]);
|
|
7757
7785
|
this.tempCanvas = this.universal.isServer ? null : document.createElement("canvas");
|
|
7758
7786
|
this.shouldDraw = !this.universal.isServer;
|
|
7759
7787
|
this.rotation = 0;
|
|
7760
7788
|
this.canvasWidth = 0;
|
|
7761
7789
|
this.canvasHeight = 0;
|
|
7762
7790
|
this.hoveredIndex = null;
|
|
7763
|
-
this.itemComponents = [];
|
|
7764
7791
|
this.touched = false;
|
|
7765
7792
|
this.deltaX = 0;
|
|
7766
7793
|
this.deltaY = 0;
|
|
@@ -7777,6 +7804,9 @@ class InteractiveCanvasComponent {
|
|
|
7777
7804
|
}
|
|
7778
7805
|
ngOnChanges() {
|
|
7779
7806
|
this.params = this.params || {};
|
|
7807
|
+
this.renderCtx = this.renderCtx || {};
|
|
7808
|
+
this.beforeItems = this.beforeItems || [];
|
|
7809
|
+
this.afterItems = this.afterItems || [];
|
|
7780
7810
|
this.resize();
|
|
7781
7811
|
}
|
|
7782
7812
|
ngAfterViewInit() {
|
|
@@ -7817,16 +7847,19 @@ class InteractiveCanvasComponent {
|
|
|
7817
7847
|
this.canvasWidth = canvas[axisX];
|
|
7818
7848
|
this.canvasHeight = canvas[axisY];
|
|
7819
7849
|
this.fullHeight = this.realHeight * this.ratio;
|
|
7850
|
+
this.viewRatio = Math.round(this.canvasHeight / this.fullHeight * 100) / 100;
|
|
7820
7851
|
this.fixRotation();
|
|
7821
7852
|
}
|
|
7822
7853
|
onTouchStart($event) {
|
|
7823
7854
|
this.hoveredIndex = this.getIndexUnderPointer($event.touches.item(0));
|
|
7855
|
+
this.lockedIndex = this.hoveredIndex;
|
|
7824
7856
|
this.touched = true;
|
|
7825
7857
|
}
|
|
7826
7858
|
onTouchEnd($event) {
|
|
7827
7859
|
this.selectItem($event.touches.item(0));
|
|
7828
7860
|
}
|
|
7829
|
-
onMouseDown() {
|
|
7861
|
+
onMouseDown($event) {
|
|
7862
|
+
this.lockedIndex = this.getIndexUnderPointer($event);
|
|
7830
7863
|
this.touched = true;
|
|
7831
7864
|
}
|
|
7832
7865
|
onMouseUp($event) {
|
|
@@ -7842,40 +7875,52 @@ class InteractiveCanvasComponent {
|
|
|
7842
7875
|
this.hoveredIndex = null;
|
|
7843
7876
|
this.updateCursor();
|
|
7844
7877
|
}
|
|
7845
|
-
onPanStart(
|
|
7846
|
-
this.lockedIndex = this.getIndexUnderPointer($event?.pointers[0]);
|
|
7878
|
+
onPanStart() {
|
|
7847
7879
|
this.deltaX = 0;
|
|
7848
7880
|
this.deltaY = 0;
|
|
7849
7881
|
}
|
|
7850
|
-
|
|
7882
|
+
onPanMove($event) {
|
|
7851
7883
|
const item = this.lockedItem;
|
|
7852
7884
|
const deltaX = ($event.deltaX - this.deltaX) / this.ratio;
|
|
7853
7885
|
const deltaY = ($event.deltaY - this.deltaY) / this.ratio;
|
|
7886
|
+
const data = {
|
|
7887
|
+
canvas: this,
|
|
7888
|
+
pointers: $event.pointers,
|
|
7889
|
+
item,
|
|
7890
|
+
deltaX,
|
|
7891
|
+
deltaY
|
|
7892
|
+
};
|
|
7893
|
+
if (this.horizontal) {
|
|
7894
|
+
data.deltaX = -deltaY;
|
|
7895
|
+
data.deltaY = +deltaX;
|
|
7896
|
+
}
|
|
7854
7897
|
if (item) {
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
: { pointers: $event.pointers, deltaX, deltaY };
|
|
7858
|
-
data.item = item;
|
|
7859
|
-
item.move(data.deltaX, data.deltaY);
|
|
7860
|
-
this.itemPan.emit(data);
|
|
7898
|
+
item.moveBy(data.deltaX, data.deltaY);
|
|
7899
|
+
this.onItemPan.emit(data);
|
|
7861
7900
|
}
|
|
7862
7901
|
else if (this.resizeMode == "fill") {
|
|
7863
7902
|
this.rotation += (this.horizontal ? deltaX : deltaY) / this.realHeight * 360;
|
|
7864
7903
|
this.fixRotation();
|
|
7904
|
+
this.onPan.emit(data);
|
|
7865
7905
|
}
|
|
7866
7906
|
this.deltaX = $event.deltaX;
|
|
7867
7907
|
this.deltaY = $event.deltaY;
|
|
7868
7908
|
}
|
|
7869
7909
|
onPanEnd() {
|
|
7870
7910
|
const item = this.lockedItem;
|
|
7911
|
+
const data = {
|
|
7912
|
+
canvas: this,
|
|
7913
|
+
pointers: [],
|
|
7914
|
+
deltaX: 0,
|
|
7915
|
+
deltaY: 0,
|
|
7916
|
+
item
|
|
7917
|
+
};
|
|
7871
7918
|
if (item) {
|
|
7872
7919
|
item.moveEnd();
|
|
7873
|
-
this.
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
item
|
|
7878
|
-
});
|
|
7920
|
+
this.onItemPanned.emit(data);
|
|
7921
|
+
}
|
|
7922
|
+
else {
|
|
7923
|
+
this.onPanned.emit(data);
|
|
7879
7924
|
}
|
|
7880
7925
|
this.lockedIndex = -1;
|
|
7881
7926
|
}
|
|
@@ -7883,16 +7928,19 @@ class InteractiveCanvasComponent {
|
|
|
7883
7928
|
if (this.fullHeight <= 0)
|
|
7884
7929
|
return;
|
|
7885
7930
|
this.rotation = ((this.rotation + 180) % 360 + 360) % 360 - 180;
|
|
7931
|
+
this.rotation = Math.round(this.rotation * 100) / 100;
|
|
7886
7932
|
this.basePan = (this.rotation / 360 - 1) * this.fullHeight + this.canvasHeight * this.panOffset;
|
|
7887
|
-
|
|
7933
|
+
this.cycles = this.resizeMode == "fit"
|
|
7888
7934
|
? [0] : [this.basePan - this.fullHeight, this.basePan, this.basePan + this.fullHeight];
|
|
7889
|
-
this.
|
|
7890
|
-
item.calcShapes(
|
|
7935
|
+
this.items.forEach(item => {
|
|
7936
|
+
item.calcShapes();
|
|
7891
7937
|
});
|
|
7938
|
+
this.onRotate.emit(this.rotation);
|
|
7892
7939
|
}
|
|
7893
7940
|
fixItems() {
|
|
7894
|
-
|
|
7895
|
-
this.
|
|
7941
|
+
const items = this.itemList.toArray();
|
|
7942
|
+
this.$items.next(items);
|
|
7943
|
+
items.forEach((item, ix) => {
|
|
7896
7944
|
item.canvas = this;
|
|
7897
7945
|
item.index = ix;
|
|
7898
7946
|
});
|
|
@@ -7919,7 +7967,7 @@ class InteractiveCanvasComponent {
|
|
|
7919
7967
|
: new Point(pointer.clientX - canvasRect.left, pointer.clientY - canvasRect.top);
|
|
7920
7968
|
const length = this.items.length;
|
|
7921
7969
|
for (let ix = 0; ix < length; ix++) {
|
|
7922
|
-
const item = this.
|
|
7970
|
+
const item = this.items[ix];
|
|
7923
7971
|
if (item?.hit(point)) {
|
|
7924
7972
|
return item.disabled ? null : ix;
|
|
7925
7973
|
}
|
|
@@ -7928,7 +7976,6 @@ class InteractiveCanvasComponent {
|
|
|
7928
7976
|
}
|
|
7929
7977
|
updateCursor() {
|
|
7930
7978
|
const cursor = this.getCursor();
|
|
7931
|
-
this.renderer.setStyle(this.canvasElem.nativeElement, "cursor", cursor);
|
|
7932
7979
|
this.renderer.setStyle(this.containerElem.nativeElement, "cursor", cursor);
|
|
7933
7980
|
}
|
|
7934
7981
|
getCursor() {
|
|
@@ -7994,23 +8041,34 @@ class InteractiveCanvasComponent {
|
|
|
7994
8041
|
async draw() {
|
|
7995
8042
|
const ctx = this.ctx;
|
|
7996
8043
|
const canvas = ctx.canvas;
|
|
8044
|
+
if (canvas.width < 1 || canvas.height < 1)
|
|
8045
|
+
return;
|
|
7997
8046
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
7998
8047
|
ctx.save();
|
|
7999
8048
|
if (this.horizontal) {
|
|
8000
8049
|
ctx.rotate(-Math.PI / 2);
|
|
8001
8050
|
ctx.translate(-this.canvasWidth, 0);
|
|
8002
8051
|
}
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8052
|
+
try {
|
|
8053
|
+
for (const renderer of this.beforeItems) {
|
|
8054
|
+
await renderer(this, this.renderCtx);
|
|
8055
|
+
}
|
|
8056
|
+
await this.drawItems();
|
|
8057
|
+
for (const renderer of this.afterItems) {
|
|
8058
|
+
await renderer(this, this.renderCtx);
|
|
8059
|
+
}
|
|
8060
|
+
}
|
|
8061
|
+
catch (e) {
|
|
8062
|
+
console.warn(`There was an error rendering the canvas: ${e}`);
|
|
8063
|
+
}
|
|
8006
8064
|
ctx.restore();
|
|
8007
8065
|
}
|
|
8008
8066
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, deps: [{ token: i0.Renderer2 }, { token: UniversalService }, { token: i0.ElementRef }, { token: ROOT_ELEMENT }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8009
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: InteractiveCanvasComponent, isStandalone: false, selector: "interactive-canvas", inputs: { debug: "debug", horizontal: "horizontal", selectedIndex: "selectedIndex", resizeMode: "resizeMode", realWidth: "realWidth", realHeight: "realHeight", panOffset: "panOffset", params: "params", beforeItems: "beforeItems", afterItems: "afterItems" }, outputs: { selectedIndexChange: "selectedIndexChange",
|
|
8067
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: InteractiveCanvasComponent, isStandalone: false, selector: "interactive-canvas", inputs: { debug: "debug", horizontal: "horizontal", selectedIndex: "selectedIndex", resizeMode: "resizeMode", realWidth: "realWidth", realHeight: "realHeight", panOffset: "panOffset", params: "params", renderCtx: "renderCtx", beforeItems: "beforeItems", afterItems: "afterItems" }, outputs: { selectedIndexChange: "selectedIndexChange", onRotate: "onRotate", onItemPan: "onItemPan", onItemPanned: "onItemPanned", onPan: "onPan", onPanned: "onPanned" }, host: { listeners: { "window:touchend": "onTouchEnd($event)", "window:mouseup": "onMouseUp($event)" } }, queries: [{ propertyName: "itemList", predicate: InteractiveItemComponent }], viewQueries: [{ propertyName: "containerElem", first: true, predicate: ["containerElem"], descendants: true, static: true }, { propertyName: "canvasElem", first: true, predicate: ["canvasElem"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-container', horizontal ? 'horizontal' : 'vertical']\"\n (resize)=\"resize()\"\n (touchstart)=\"onTouchStart($event)\"\n (mousedown)=\"onMouseDown($event)\"\n (mousemove)=\"onMouseMove($event)\"\n (mouseleave)=\"onMouseLeave()\"\n (panend)=\"onPanEnd()\"\n (panmove)=\"onPanMove($event)\"\n (panstart)=\"onPanStart()\">\n <canvas #canvasElem class=\"interactive-canvas-element\"></canvas>\n</div>\n", styles: [".interactive-canvas-container{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center}.interactive-canvas-container .interactive-canvas-element{position:absolute;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
8010
8068
|
}
|
|
8011
8069
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, decorators: [{
|
|
8012
8070
|
type: Component,
|
|
8013
|
-
args: [{ standalone: false, selector: "interactive-canvas", template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-
|
|
8071
|
+
args: [{ standalone: false, selector: "interactive-canvas", template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-container', horizontal ? 'horizontal' : 'vertical']\"\n (resize)=\"resize()\"\n (touchstart)=\"onTouchStart($event)\"\n (mousedown)=\"onMouseDown($event)\"\n (mousemove)=\"onMouseMove($event)\"\n (mouseleave)=\"onMouseLeave()\"\n (panend)=\"onPanEnd()\"\n (panmove)=\"onPanMove($event)\"\n (panstart)=\"onPanStart()\">\n <canvas #canvasElem class=\"interactive-canvas-element\"></canvas>\n</div>\n", styles: [".interactive-canvas-container{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center}.interactive-canvas-container .interactive-canvas-element{position:absolute;pointer-events:none}\n"] }]
|
|
8014
8072
|
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: UniversalService }, { type: i0.ElementRef }, { type: HTMLElement, decorators: [{
|
|
8015
8073
|
type: Inject,
|
|
8016
8074
|
args: [ROOT_ELEMENT]
|
|
@@ -8030,15 +8088,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
8030
8088
|
type: Input
|
|
8031
8089
|
}], params: [{
|
|
8032
8090
|
type: Input
|
|
8091
|
+
}], renderCtx: [{
|
|
8092
|
+
type: Input
|
|
8033
8093
|
}], beforeItems: [{
|
|
8034
8094
|
type: Input
|
|
8035
8095
|
}], afterItems: [{
|
|
8036
8096
|
type: Input
|
|
8037
8097
|
}], selectedIndexChange: [{
|
|
8038
8098
|
type: Output
|
|
8039
|
-
}],
|
|
8099
|
+
}], onRotate: [{
|
|
8100
|
+
type: Output
|
|
8101
|
+
}], onItemPan: [{
|
|
8102
|
+
type: Output
|
|
8103
|
+
}], onItemPanned: [{
|
|
8104
|
+
type: Output
|
|
8105
|
+
}], onPan: [{
|
|
8040
8106
|
type: Output
|
|
8041
|
-
}],
|
|
8107
|
+
}], onPanned: [{
|
|
8042
8108
|
type: Output
|
|
8043
8109
|
}], containerElem: [{
|
|
8044
8110
|
type: ViewChild,
|