@wolkabout/commons 0.0.63 → 0.0.65

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.
@@ -5573,6 +5573,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5573
5573
  }], ctorParameters: () => [{ type: i1$5.DomSanitizer }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }] } });
5574
5574
 
5575
5575
  class StandardListViewComponent {
5576
+ scrollViewport = viewChild(CdkVirtualScrollViewport, ...(ngDevMode ? [{ debugName: "scrollViewport" }] : []));
5576
5577
  dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : []));
5577
5578
  dataControl = input.required(...(ngDevMode ? [{ debugName: "dataControl" }] : []));
5578
5579
  position = input('outer', ...(ngDevMode ? [{ debugName: "position" }] : []));
@@ -5601,7 +5602,31 @@ class StandardListViewComponent {
5601
5602
  }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
5602
5603
  itemSelected = output();
5603
5604
  itemTemplate = contentChild('standardListItemTemplate', ...(ngDevMode ? [{ debugName: "itemTemplate" }] : []));
5605
+ initialSelectionItemIndex = signal(null, ...(ngDevMode ? [{ debugName: "initialSelectionItemIndex" }] : []));
5606
+ scrolledToBottom = signal(false, ...(ngDevMode ? [{ debugName: "scrolledToBottom" }] : []));
5607
+ scrollSubscription = null;
5604
5608
  constructor(destroyRef) {
5609
+ effect(() => {
5610
+ const viewport = this.scrollViewport();
5611
+ const index = this.initialSelectionItemIndex();
5612
+ if (viewport && index) {
5613
+ setTimeout(() => {
5614
+ viewport.scrollToIndex(index);
5615
+ this.initialSelectionItemIndex.set(null);
5616
+ }, 0);
5617
+ }
5618
+ });
5619
+ effect(() => {
5620
+ const viewport = this.scrollViewport();
5621
+ if (viewport && !this.scrollSubscription) {
5622
+ this.scrollSubscription = viewport.elementScrolled().pipe(takeUntilDestroyed(destroyRef), map(() => {
5623
+ const { scrollTop, scrollHeight, clientHeight } = viewport.elementRef.nativeElement;
5624
+ return scrollTop + clientHeight >= scrollHeight - 1;
5625
+ }), distinctUntilChanged()).subscribe((scrolled) => {
5626
+ this.scrolledToBottom.set(scrolled);
5627
+ });
5628
+ }
5629
+ });
5605
5630
  afterNextRender(() => {
5606
5631
  const dataSource = this.dataSource();
5607
5632
  const dataControl = this.dataControl();
@@ -5618,7 +5643,10 @@ class StandardListViewComponent {
5618
5643
  }
5619
5644
  const initialSelection = dataSource.initialSelection();
5620
5645
  if (initialSelection) {
5621
- this.selectItem(items.find(item => item.id === initialSelection) ?? items[0]);
5646
+ const index = items.findIndex(item => item.id === initialSelection);
5647
+ const initialItem = index > -1 ? items[index] : items[0];
5648
+ this.selectItem(initialItem);
5649
+ this.initialSelectionItemIndex.set(index > -1 ? index : 0);
5622
5650
  }
5623
5651
  else {
5624
5652
  this.selectItem(items[0]);
@@ -5698,12 +5726,12 @@ class StandardListViewComponent {
5698
5726
  });
5699
5727
  }
5700
5728
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: StandardListViewComponent, deps: [{ token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component });
5701
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: StandardListViewComponent, isStandalone: true, selector: "app-standard-list-view", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, dataControl: { classPropertyName: "dataControl", publicName: "dataControl", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, isColoredInput: { classPropertyName: "isColoredInput", publicName: "isColoredInput", isSignal: true, isRequired: false, transformFunction: null }, hideSearch: { classPropertyName: "hideSearch", publicName: "hideSearch", isSignal: true, isRequired: false, transformFunction: null }, hideDetails: { classPropertyName: "hideDetails", publicName: "hideDetails", isSignal: true, isRequired: false, transformFunction: null }, hidePadding: { classPropertyName: "hidePadding", publicName: "hidePadding", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ["standardListItemTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"container flex h-full w-full min-w-full min-h-full relative overflow-hidden {{hidePadding() ? 'pt-0' : 'pt-2'}}\">\r\n <div [ngClass]=\"width()\" class=\"master flex shrink-0 grow-0 min-w-0\">\r\n\r\n <!-- LISTING -->\r\n <div class=\"w-full h-full flex flex-col gap-y-2 relative\">\r\n\r\n <!-- SEARCH -->\r\n @if (!hideSearch()) {\r\n <mat-form-field class=\"w-full small-input\" [ngClass]=\"{'colored-input': isColoredInput()}\">\r\n <mat-label>{{ 'COMMON.SEARCH' | translate }}</mat-label>\r\n <input matInput type=\"text\" [formControl]=\"nameSearchControl\">\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- LIST -->\r\n <div class=\"flex flex-col w-full h-full relative overflow-hidden\">\r\n @if (!loadingData()) {\r\n @if (filteredItems(); as items) {\r\n @if (items.length) {\r\n <div class=\"flex flex-col w-full grow shrink overflow-y-auto overflow-x-hidden\" [overflowClass]=\"'pr-4'\">\r\n @for (item of items; track $index) {\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate() || defaultTemplate\" [ngTemplateOutletContext]=\"{$implicit: item, selectedItem: selectedItem(), selectItem: selectItem.bind(this)}\"/>\r\n\r\n <!--DEFAULT TEMPLATE-->\r\n <ng-template #defaultTemplate>\r\n <mat-card class=\"mb-2 cursor-pointer\" (click)=\"selectItem(item)\"\r\n [class]=\"selectedItem()?.id === item.id ? 'selected-item' : 'regular-item hover:bg-hover-color'\"\r\n [appScrollIntoView]=\"selectedItem()?.id === item.id\"\r\n [matTooltip]=\"item.name\" matTooltipPosition=\"right\">\r\n <div class=\"px-3 flex flex-row items-center gap-x-2 item-card\">\r\n @if (item.icon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n <span [ngClass]=\"selectedItem()?.id === item.id ? 'text-mat-sys-surface-container' : 'text-mat-sys-on-surface'\" class=\"truncate flex-1\">{{ item.name }}</span>\r\n @if (item.rightIcon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n </div>\r\n </mat-card>\r\n </ng-template>\r\n }\r\n\r\n <!-- Load more -->\r\n @if (this.dataSource().isPaged && !this.dataSource().isLastPage) {\r\n <mat-card class=\"mb-2 cursor-pointer regular-item hover:bg-hover-color\" (click)=\"loadMore()\">\r\n <div class=\"px-3 flex flex-row justify-center items-center gap-x-2 item-card\">\r\n @if (loadingPage()) {\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n } @else {\r\n <span class=\"text-mat-sys-on-surface\">{{ 'COMMON.LOAD_MORE' | translate }}</span>\r\n }\r\n </div>\r\n </mat-card>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <ng-content select=\"[app-no-items-message]\"></ng-content>\r\n </div>\r\n }\r\n }\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n </div>\r\n }\r\n\r\n <!-- ACTIONS (bottom right of the listing) -->\r\n <div class=\"absolute bottom-0 right-0 z-10\">\r\n <ng-content select=\"[app-actions]\"/>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n @if (!hideDetails()) {\r\n <mat-divider [vertical]=\"true\"/>\r\n\r\n <!-- DETAILS -->\r\n <div class=\"details flex shrink grow overflow-hidden\">\r\n <ng-content select=\"[app-details]\"/>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;height:100%;width:100%;overflow:hidden}mat-card,.item-card{height:40px!important}.container{background-color:var(--base-color-50)}.container .master{padding-right:16px}.container .details{padding-left:16px}.selected-item{background:var(--mat-sys-primary);fill:var(--mat-sys-on-primary);color:var(--mat-sys-on-primary)}.regular-item{fill:var(--mat-sys-primary);color:var(--mat-sys-primary)}\n"], dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: i1$6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i9.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: OverflowClassDirective, selector: "[overflowClass]", inputs: ["overflowClass"] }, { kind: "directive", type: ScrollIntoViewDirective, selector: "[appScrollIntoView]", inputs: ["appScrollIntoView"] }, { kind: "component", type: IconComponent, selector: "app-icon", inputs: ["icon"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
5729
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: StandardListViewComponent, isStandalone: true, selector: "app-standard-list-view", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, dataControl: { classPropertyName: "dataControl", publicName: "dataControl", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, isColoredInput: { classPropertyName: "isColoredInput", publicName: "isColoredInput", isSignal: true, isRequired: false, transformFunction: null }, hideSearch: { classPropertyName: "hideSearch", publicName: "hideSearch", isSignal: true, isRequired: false, transformFunction: null }, hideDetails: { classPropertyName: "hideDetails", publicName: "hideDetails", isSignal: true, isRequired: false, transformFunction: null }, hidePadding: { classPropertyName: "hidePadding", publicName: "hidePadding", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ["standardListItemTemplate"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"container flex h-full w-full min-w-full min-h-full relative overflow-hidden {{hidePadding() ? 'pt-0' : 'pt-2'}}\">\r\n <div [ngClass]=\"width()\" class=\"master flex shrink-0 grow-0 min-w-0\">\r\n\r\n <!-- LISTING -->\r\n <div class=\"w-full h-full flex flex-col gap-y-2 relative\">\r\n\r\n <!-- SEARCH -->\r\n @if (!hideSearch()) {\r\n <mat-form-field class=\"w-full small-input\" [ngClass]=\"{'colored-input': isColoredInput()}\">\r\n <mat-label>{{ 'COMMON.SEARCH' | translate }}</mat-label>\r\n <input matInput type=\"text\" [formControl]=\"nameSearchControl\">\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- LIST -->\r\n <div class=\"flex flex-col w-full h-full relative overflow-hidden\">\r\n @if (!loadingData()) {\r\n @if (filteredItems(); as items) {\r\n @if (items.length) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"48\" class=\"viewport\" [overflowClass]=\"'standard-list-overflow-padding'\">\r\n <ng-container *cdkVirtualFor=\"let item of items; let i = index\">\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate() || defaultTemplate\" [ngTemplateOutletContext]=\"{$implicit: item, selectedItem: selectedItem(), selectItem: selectItem.bind(this)}\"/>\r\n <!--DEFAULT TEMPLATE-->\r\n <ng-template #defaultTemplate>\r\n <mat-card class=\"mb-2 cursor-pointer\" (click)=\"selectItem(item)\"\r\n [class]=\"selectedItem()?.id === item.id ? 'selected-item' : 'regular-item hover:bg-hover-color'\"\r\n [matTooltip]=\"item.name\" matTooltipPosition=\"right\">\r\n <div class=\"px-3 flex flex-row items-center gap-x-2 item-card\">\r\n @if (item.icon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n <span [ngClass]=\"selectedItem()?.id === item.id ? 'text-mat-sys-surface-container' : 'text-mat-sys-on-surface'\" class=\"truncate flex-1\">{{ item.name }}</span>\r\n @if (item.rightIcon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n </div>\r\n </mat-card>\r\n </ng-template>\r\n </ng-container>\r\n\r\n <!-- Load more -->\r\n @if (this.dataSource().isPaged && !this.dataSource().isLastPage && this.scrolledToBottom()) {\r\n <mat-card class=\"mb-2 cursor-pointer regular-item hover:bg-hover-color\" (click)=\"loadMore()\">\r\n <div class=\"px-3 flex flex-row justify-center items-center gap-x-2 item-card\">\r\n @if (loadingPage()) {\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n } @else {\r\n <span class=\"text-mat-sys-on-surface\">{{ 'COMMON.LOAD_MORE' | translate }}</span>\r\n }\r\n </div>\r\n </mat-card>\r\n }\r\n </cdk-virtual-scroll-viewport>\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <ng-content select=\"[app-no-items-message]\"></ng-content>\r\n </div>\r\n }\r\n }\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n </div>\r\n }\r\n\r\n <!-- ACTIONS (bottom right of the listing) -->\r\n <div class=\"absolute bottom-0 right-0 z-10\">\r\n <ng-content select=\"[app-actions]\"/>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n @if (!hideDetails()) {\r\n <mat-divider [vertical]=\"true\"/>\r\n\r\n <!-- DETAILS -->\r\n <div class=\"details flex shrink grow overflow-hidden\">\r\n <ng-content select=\"[app-details]\"/>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;height:100%;width:100%;overflow:hidden}:host ::ng-deep .cdk-virtual-scroll-content-wrapper{max-width:100%}:host ::ng-deep .standard-list-overflow-padding .cdk-virtual-scroll-content-wrapper{padding-right:1rem}mat-card,.item-card{height:40px!important}.container{background-color:var(--base-color-50)}.container .master{padding-right:16px}.container .details{padding-left:16px}.selected-item{background:var(--mat-sys-primary);fill:var(--mat-sys-on-primary);color:var(--mat-sys-on-primary)}.regular-item{fill:var(--mat-sys-primary);color:var(--mat-sys-primary)}.viewport{display:block;width:100%;height:100%;overflow-y:auto;overflow-x:hidden}\n"], dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: i1$6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "directive", type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i9.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i9.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconComponent, selector: "app-icon", inputs: ["icon"] }, { kind: "directive", type: OverflowClassDirective, selector: "[overflowClass]", inputs: ["overflowClass"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
5702
5730
  }
5703
5731
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: StandardListViewComponent, decorators: [{
5704
5732
  type: Component,
5705
- args: [{ selector: 'app-standard-list-view', imports: [SharedModule, OverflowClassDirective, ScrollIntoViewDirective, IconComponent], template: "<div class=\"container flex h-full w-full min-w-full min-h-full relative overflow-hidden {{hidePadding() ? 'pt-0' : 'pt-2'}}\">\r\n <div [ngClass]=\"width()\" class=\"master flex shrink-0 grow-0 min-w-0\">\r\n\r\n <!-- LISTING -->\r\n <div class=\"w-full h-full flex flex-col gap-y-2 relative\">\r\n\r\n <!-- SEARCH -->\r\n @if (!hideSearch()) {\r\n <mat-form-field class=\"w-full small-input\" [ngClass]=\"{'colored-input': isColoredInput()}\">\r\n <mat-label>{{ 'COMMON.SEARCH' | translate }}</mat-label>\r\n <input matInput type=\"text\" [formControl]=\"nameSearchControl\">\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- LIST -->\r\n <div class=\"flex flex-col w-full h-full relative overflow-hidden\">\r\n @if (!loadingData()) {\r\n @if (filteredItems(); as items) {\r\n @if (items.length) {\r\n <div class=\"flex flex-col w-full grow shrink overflow-y-auto overflow-x-hidden\" [overflowClass]=\"'pr-4'\">\r\n @for (item of items; track $index) {\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate() || defaultTemplate\" [ngTemplateOutletContext]=\"{$implicit: item, selectedItem: selectedItem(), selectItem: selectItem.bind(this)}\"/>\r\n\r\n <!--DEFAULT TEMPLATE-->\r\n <ng-template #defaultTemplate>\r\n <mat-card class=\"mb-2 cursor-pointer\" (click)=\"selectItem(item)\"\r\n [class]=\"selectedItem()?.id === item.id ? 'selected-item' : 'regular-item hover:bg-hover-color'\"\r\n [appScrollIntoView]=\"selectedItem()?.id === item.id\"\r\n [matTooltip]=\"item.name\" matTooltipPosition=\"right\">\r\n <div class=\"px-3 flex flex-row items-center gap-x-2 item-card\">\r\n @if (item.icon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n <span [ngClass]=\"selectedItem()?.id === item.id ? 'text-mat-sys-surface-container' : 'text-mat-sys-on-surface'\" class=\"truncate flex-1\">{{ item.name }}</span>\r\n @if (item.rightIcon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n </div>\r\n </mat-card>\r\n </ng-template>\r\n }\r\n\r\n <!-- Load more -->\r\n @if (this.dataSource().isPaged && !this.dataSource().isLastPage) {\r\n <mat-card class=\"mb-2 cursor-pointer regular-item hover:bg-hover-color\" (click)=\"loadMore()\">\r\n <div class=\"px-3 flex flex-row justify-center items-center gap-x-2 item-card\">\r\n @if (loadingPage()) {\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n } @else {\r\n <span class=\"text-mat-sys-on-surface\">{{ 'COMMON.LOAD_MORE' | translate }}</span>\r\n }\r\n </div>\r\n </mat-card>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <ng-content select=\"[app-no-items-message]\"></ng-content>\r\n </div>\r\n }\r\n }\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n </div>\r\n }\r\n\r\n <!-- ACTIONS (bottom right of the listing) -->\r\n <div class=\"absolute bottom-0 right-0 z-10\">\r\n <ng-content select=\"[app-actions]\"/>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n @if (!hideDetails()) {\r\n <mat-divider [vertical]=\"true\"/>\r\n\r\n <!-- DETAILS -->\r\n <div class=\"details flex shrink grow overflow-hidden\">\r\n <ng-content select=\"[app-details]\"/>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;height:100%;width:100%;overflow:hidden}mat-card,.item-card{height:40px!important}.container{background-color:var(--base-color-50)}.container .master{padding-right:16px}.container .details{padding-left:16px}.selected-item{background:var(--mat-sys-primary);fill:var(--mat-sys-on-primary);color:var(--mat-sys-on-primary)}.regular-item{fill:var(--mat-sys-primary);color:var(--mat-sys-primary)}\n"] }]
5706
- }], ctorParameters: () => [{ type: i0.DestroyRef }], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], dataControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataControl", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], isColoredInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "isColoredInput", required: false }] }], hideSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideSearch", required: false }] }], hideDetails: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDetails", required: false }] }], hidePadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePadding", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], itemTemplate: [{ type: i0.ContentChild, args: ['standardListItemTemplate', { isSignal: true }] }] } });
5733
+ args: [{ selector: 'app-standard-list-view', imports: [SharedModule, IconComponent, OverflowClassDirective, CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport], template: "<div class=\"container flex h-full w-full min-w-full min-h-full relative overflow-hidden {{hidePadding() ? 'pt-0' : 'pt-2'}}\">\r\n <div [ngClass]=\"width()\" class=\"master flex shrink-0 grow-0 min-w-0\">\r\n\r\n <!-- LISTING -->\r\n <div class=\"w-full h-full flex flex-col gap-y-2 relative\">\r\n\r\n <!-- SEARCH -->\r\n @if (!hideSearch()) {\r\n <mat-form-field class=\"w-full small-input\" [ngClass]=\"{'colored-input': isColoredInput()}\">\r\n <mat-label>{{ 'COMMON.SEARCH' | translate }}</mat-label>\r\n <input matInput type=\"text\" [formControl]=\"nameSearchControl\">\r\n <mat-icon matSuffix>search</mat-icon>\r\n </mat-form-field>\r\n }\r\n\r\n <!-- LIST -->\r\n <div class=\"flex flex-col w-full h-full relative overflow-hidden\">\r\n @if (!loadingData()) {\r\n @if (filteredItems(); as items) {\r\n @if (items.length) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"48\" class=\"viewport\" [overflowClass]=\"'standard-list-overflow-padding'\">\r\n <ng-container *cdkVirtualFor=\"let item of items; let i = index\">\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate() || defaultTemplate\" [ngTemplateOutletContext]=\"{$implicit: item, selectedItem: selectedItem(), selectItem: selectItem.bind(this)}\"/>\r\n <!--DEFAULT TEMPLATE-->\r\n <ng-template #defaultTemplate>\r\n <mat-card class=\"mb-2 cursor-pointer\" (click)=\"selectItem(item)\"\r\n [class]=\"selectedItem()?.id === item.id ? 'selected-item' : 'regular-item hover:bg-hover-color'\"\r\n [matTooltip]=\"item.name\" matTooltipPosition=\"right\">\r\n <div class=\"px-3 flex flex-row items-center gap-x-2 item-card\">\r\n @if (item.icon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n <span [ngClass]=\"selectedItem()?.id === item.id ? 'text-mat-sys-surface-container' : 'text-mat-sys-on-surface'\" class=\"truncate flex-1\">{{ item.name }}</span>\r\n @if (item.rightIcon; as icon) {\r\n <app-icon [icon]=\"icon\"/>\r\n }\r\n </div>\r\n </mat-card>\r\n </ng-template>\r\n </ng-container>\r\n\r\n <!-- Load more -->\r\n @if (this.dataSource().isPaged && !this.dataSource().isLastPage && this.scrolledToBottom()) {\r\n <mat-card class=\"mb-2 cursor-pointer regular-item hover:bg-hover-color\" (click)=\"loadMore()\">\r\n <div class=\"px-3 flex flex-row justify-center items-center gap-x-2 item-card\">\r\n @if (loadingPage()) {\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n } @else {\r\n <span class=\"text-mat-sys-on-surface\">{{ 'COMMON.LOAD_MORE' | translate }}</span>\r\n }\r\n </div>\r\n </mat-card>\r\n }\r\n </cdk-virtual-scroll-viewport>\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <ng-content select=\"[app-no-items-message]\"></ng-content>\r\n </div>\r\n }\r\n }\r\n } @else {\r\n <div class=\"flex flex-col grow justify-center items-center\">\r\n <mat-spinner diameter=\"30\"></mat-spinner>\r\n </div>\r\n }\r\n\r\n <!-- ACTIONS (bottom right of the listing) -->\r\n <div class=\"absolute bottom-0 right-0 z-10\">\r\n <ng-content select=\"[app-actions]\"/>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n @if (!hideDetails()) {\r\n <mat-divider [vertical]=\"true\"/>\r\n\r\n <!-- DETAILS -->\r\n <div class=\"details flex shrink grow overflow-hidden\">\r\n <ng-content select=\"[app-details]\"/>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block;height:100%;width:100%;overflow:hidden}:host ::ng-deep .cdk-virtual-scroll-content-wrapper{max-width:100%}:host ::ng-deep .standard-list-overflow-padding .cdk-virtual-scroll-content-wrapper{padding-right:1rem}mat-card,.item-card{height:40px!important}.container{background-color:var(--base-color-50)}.container .master{padding-right:16px}.container .details{padding-left:16px}.selected-item{background:var(--mat-sys-primary);fill:var(--mat-sys-on-primary);color:var(--mat-sys-on-primary)}.regular-item{fill:var(--mat-sys-primary);color:var(--mat-sys-primary)}.viewport{display:block;width:100%;height:100%;overflow-y:auto;overflow-x:hidden}\n"] }]
5734
+ }], ctorParameters: () => [{ type: i0.DestroyRef }], propDecorators: { scrollViewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], dataControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataControl", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], isColoredInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "isColoredInput", required: false }] }], hideSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideSearch", required: false }] }], hideDetails: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDetails", required: false }] }], hidePadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePadding", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], itemTemplate: [{ type: i0.ContentChild, args: ['standardListItemTemplate', { isSignal: true }] }] } });
5707
5735
 
5708
5736
  class StandardListDataControl {
5709
5737
  _changeSelection$ = new BehaviorSubject(null);