@yuuvis/client-framework 2.20.0 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/actions/lib/actions.interface.d.ts +21 -1
  2. package/actions/lib/actions.module.d.ts +2 -3
  3. package/actions/lib/actions.service.d.ts +13 -5
  4. package/actions/lib/components/contextmenu/contextmenu.component.d.ts +1 -1
  5. package/fesm2022/yuuvis-client-framework-actions.mjs +82 -53
  6. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  7. package/fesm2022/yuuvis-client-framework-list.mjs +2 -0
  8. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-object-details.mjs +2 -2
  10. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +4 -4
  12. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  13. package/fesm2022/yuuvis-client-framework-renderer.mjs +3 -3
  14. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
  15. package/fesm2022/yuuvis-client-framework-tile-list.mjs +132 -93
  16. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  17. package/fesm2022/yuuvis-client-framework.mjs +75 -19
  18. package/fesm2022/yuuvis-client-framework.mjs.map +1 -1
  19. package/lib/assets/i18n/de.json +1 -0
  20. package/lib/assets/i18n/en.json +1 -0
  21. package/lib/models/snack-bar/snack-bar-data.model.d.ts +3 -2
  22. package/lib/models/snack-bar/snack-bar-options.model.d.ts +5 -1
  23. package/lib/services/snack-bar/snack-bar.service.d.ts +11 -8
  24. package/package.json +4 -4
  25. package/tile-list/index.d.ts +6 -5
  26. package/tile-list/lib/tile-actions-menu/tile-actions-menu.component.d.ts +2 -1
  27. package/lib/assets/i18n/ar.json +0 -217
@@ -1,17 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, viewChild, ChangeDetectionStrategy, Component, Injectable, inject, ViewContainerRef, effect, Directive, DestroyRef, ElementRef, contentChild, viewChildren, computed, signal, linkedSignal, untracked } from '@angular/core';
2
+ import { input, output, viewChild, ChangeDetectionStrategy, Component, forwardRef, Injectable, inject, ViewContainerRef, effect, Directive, DestroyRef, ElementRef, ChangeDetectorRef, contentChild, viewChildren, computed, signal, linkedSignal, untracked } from '@angular/core';
3
+ import * as i4 from '@angular/material/icon';
4
+ import { MatIcon, MatIconModule } from '@angular/material/icon';
5
+ import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
6
+ import { MatProgressSpinner } from '@angular/material/progress-spinner';
7
+ import * as i2$1 from '@angular/material/tooltip';
8
+ import { MatTooltip, MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipModule } from '@angular/material/tooltip';
3
9
  import * as i1 from '@yuuvis/client-core';
4
10
  import { ObjectConfigService, DmsService, SearchService, DmsObject, BaseObjectTypeField, TranslateModule, SystemService, ContentStreamField, Utils, Sort } from '@yuuvis/client-core';
5
11
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
6
12
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
13
  import * as i1$2 from '@angular/forms';
8
14
  import { ReactiveFormsModule, FormsModule } from '@angular/forms';
9
- import * as i4 from '@angular/material/icon';
10
- import { MatIcon, MatIconModule } from '@angular/material/icon';
11
- import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
12
15
  import { MatPaginatorModule } from '@angular/material/paginator';
13
- import * as i2$1 from '@angular/material/tooltip';
14
- import { MatTooltip, MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltipModule } from '@angular/material/tooltip';
15
16
  import { ActionsService } from '@yuuvis/client-framework/actions';
16
17
  import * as i2 from '@yuuvis/client-framework/list';
17
18
  import { YuvListModule } from '@yuuvis/client-framework/list';
@@ -19,67 +20,46 @@ import * as i3 from '@yuuvis/client-framework/query-list';
19
20
  import { YuvQueryListModule } from '@yuuvis/client-framework/query-list';
20
21
  import { RendererDirective } from '@yuuvis/client-framework/renderer';
21
22
  import { YmtMatIconRegistryService, YmtIconButtonDirective, YmtButtonDirective } from '@yuuvis/material';
22
- import { switchMap } from 'rxjs';
23
+ import { switchMap, forkJoin, take } from 'rxjs';
24
+ import { NgClass, CommonModule } from '@angular/common';
23
25
  import * as i1$1 from '@angular/material/button';
24
26
  import { MatButtonModule } from '@angular/material/button';
25
27
  import { MatDialogModule, MatDialog } from '@angular/material/dialog';
28
+ import { TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
26
29
  import { MatFormFieldModule } from '@angular/material/form-field';
27
30
  import * as i3$1 from '@angular/material/select';
28
31
  import { MatSelectModule } from '@angular/material/select';
29
32
  import { DialogComponent } from '@yuuvis/client-framework/common';
30
- import { NgClass, CommonModule } from '@angular/common';
31
33
  import { ObjectTypeIconComponent } from '@yuuvis/client-framework/icons';
32
- import { TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
33
34
 
34
35
  class TileActionsMenuComponent {
35
36
  constructor() {
36
37
  this.actions = input.required();
38
+ this.loading = input(false);
37
39
  this.itemSelect = output();
38
40
  this.matMenu = viewChild.required('menuRef');
39
41
  }
40
42
  itemClicked(event, action) {
41
43
  event.stopPropagation();
42
44
  event.preventDefault();
45
+ if (action.disabled)
46
+ return;
43
47
  this.itemSelect.emit(action);
44
48
  }
45
49
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TileActionsMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
46
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: TileActionsMenuComponent, isStandalone: true, selector: "yuv-tile-actions-menu", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: { position: 'right' } }], viewQueries: [{ propertyName: "matMenu", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
47
- <mat-menu #menuRef>
48
- @for (action of actions(); track action.id) {
49
- <button
50
- mat-menu-item
51
- (click)="itemClicked($event, action)"
52
- [matTooltip]="action.description"
53
- [matTooltipDisabled]="!action.description"
54
- >
55
- @if (action.icon) {
56
- <mat-icon>{{ action.icon }}</mat-icon>
57
- }
58
- <span>{{ action.label }}</span>
59
- </button>
60
- }
61
- </mat-menu>
62
- `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
50
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: TileActionsMenuComponent, isStandalone: true, selector: "yuv-tile-actions-menu", inputs: { actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: true, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect" }, providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: { position: 'right' } }], viewQueries: [{ propertyName: "matMenu", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-menu #menuRef>\n <!-- @if (loading() && !actions().length) {\n <div class=\"loading-indicator\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n </div>\n } -->\n @for (action of actions(); track action.id) {\n @if (action.children?.length) {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n [matMenuTriggerFor]=\"subMenu.matMenu()\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n <yuv-tile-actions-menu #subMenu [actions]=\"action.children!\" (itemSelect)=\"itemSelect.emit($event)\" />\n </span>\n } @else {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n (click)=\"itemClicked($event, action)\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n </span>\n }\n }\n</mat-menu>\n", styles: [":host{display:block}.loading-indicator{display:flex;justify-content:center;padding:8px 16px}button[mat-menu-item][disabled]{opacity:var(--ymt-disabled-opacity, .38);cursor:default;pointer-events:none}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => TileActionsMenuComponent), selector: "yuv-tile-actions-menu", inputs: ["actions", "loading"], outputs: ["itemSelect"] }, { kind: "component", type: i0.forwardRef(() => MatMenu), selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i0.forwardRef(() => MatIcon), selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i0.forwardRef(() => MatMenuItem), selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i0.forwardRef(() => MatMenuTrigger), selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i0.forwardRef(() => MatTooltip), selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
63
51
  }
64
52
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TileActionsMenuComponent, decorators: [{
65
53
  type: Component,
66
- args: [{ selector: 'yuv-tile-actions-menu', imports: [MatMenu, MatIcon, MatMenuItem, MatTooltip], template: `
67
- <mat-menu #menuRef>
68
- @for (action of actions(); track action.id) {
69
- <button
70
- mat-menu-item
71
- (click)="itemClicked($event, action)"
72
- [matTooltip]="action.description"
73
- [matTooltipDisabled]="!action.description"
74
- >
75
- @if (action.icon) {
76
- <mat-icon>{{ action.icon }}</mat-icon>
77
- }
78
- <span>{{ action.label }}</span>
79
- </button>
80
- }
81
- </mat-menu>
82
- `, providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: { position: 'right' } }], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
54
+ args: [{ selector: 'yuv-tile-actions-menu', imports: [
55
+ MatMenu,
56
+ MatIcon,
57
+ MatMenuItem,
58
+ MatMenuTrigger,
59
+ MatProgressSpinner,
60
+ MatTooltip,
61
+ forwardRef(() => TileActionsMenuComponent)
62
+ ], providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: { position: 'right' } }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-menu #menuRef>\n <!-- @if (loading() && !actions().length) {\n <div class=\"loading-indicator\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n </div>\n } -->\n @for (action of actions(); track action.id) {\n @if (action.children?.length) {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n [matMenuTriggerFor]=\"subMenu.matMenu()\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n <yuv-tile-actions-menu #subMenu [actions]=\"action.children!\" (itemSelect)=\"itemSelect.emit($event)\" />\n </span>\n } @else {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n (click)=\"itemClicked($event, action)\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n </span>\n }\n }\n</mat-menu>\n", styles: [":host{display:block}.loading-indicator{display:flex;justify-content:center;padding:8px 16px}button[mat-menu-item][disabled]{opacity:var(--ymt-disabled-opacity, .38);cursor:default;pointer-events:none}\n"] }]
83
63
  }] });
84
64
 
85
65
  class TileExtensionService {
@@ -207,6 +187,7 @@ class TileListComponent {
207
187
  #objectConfigService;
208
188
  #destroyRef;
209
189
  #elRef;
190
+ #cdr;
210
191
  #actionService;
211
192
  #dmsService;
212
193
  #busy;
@@ -218,6 +199,7 @@ class TileListComponent {
218
199
  this.#objectConfigService = inject(ObjectConfigService);
219
200
  this.#destroyRef = inject(DestroyRef);
220
201
  this.#elRef = inject(ElementRef);
202
+ this.#cdr = inject(ChangeDetectorRef);
221
203
  this.#actionService = inject(ActionsService);
222
204
  this.#dmsService = inject(DmsService);
223
205
  //#endregion
@@ -547,7 +529,7 @@ class TileListComponent {
547
529
  .map((action) => this.#actionService.getActionById(action.id, this.options()?.actionContext))
548
530
  .filter((action) => action !== undefined)
549
531
  }));
550
- // untracked(() => this.items.set(items));
532
+ this.#resolveInlineActionsDisabledState(items);
551
533
  return items;
552
534
  };
553
535
  //#endregion
@@ -732,9 +714,9 @@ class TileListComponent {
732
714
  return;
733
715
  event.preventDefault();
734
716
  // if not yet selected, select
735
- if (this._selection.length === 0 || !this._selection.includes(index)) {
736
- this.#internalSelectByIndex(index, event);
737
- }
717
+ // if (this._selection.length === 0 || !this._selection.includes(index)) {
718
+ // this.#internalSelectByIndex(index, event);
719
+ // }
738
720
  setTimeout(() => {
739
721
  this.ctxMenu.emit({ event, selection: this.selection() });
740
722
  // eslint-disable-next-line @typescript-eslint/no-magic-numbers
@@ -757,6 +739,8 @@ class TileListComponent {
757
739
  executeAction(tileData, action, event) {
758
740
  event.preventDefault();
759
741
  event.stopPropagation();
742
+ if (action.disabled)
743
+ return;
760
744
  const selectedIds = this.selection();
761
745
  const ids = selectedIds.includes(tileData.id) ? selectedIds : [tileData.id];
762
746
  this.#dmsService
@@ -830,14 +814,13 @@ class TileListComponent {
830
814
  * @param objects `DmsObject` instances to prepend to the visible list.
831
815
  */
832
816
  dropItems(objects) {
833
- const mappedItems = this.#mapToTileData(objects);
834
- const items = mappedItems.map((item) => ({
835
- ...item,
836
- actions: (item.actions || [])
837
- .map((objectConfigAction) => this.#actionService.getActionById(objectConfigAction.id, this.options()?.actionContext))
838
- .filter((action) => action !== undefined)
839
- }));
840
- this.items.set([...items, ...this.items()]);
817
+ const items = this.#updateItems(objects);
818
+ if (items.length > 0 && this._selection.length > 0) {
819
+ this._selection = this._selection.map((i) => i + items.length);
820
+ if (this._lastSelection !== undefined) {
821
+ this._lastSelection += items.length;
822
+ }
823
+ }
841
824
  this.list().dropItems(items);
842
825
  }
843
826
  /**
@@ -872,6 +855,14 @@ class TileListComponent {
872
855
  * @param updates Array of `{ index, value }` pairs describing which tiles to patch.
873
856
  */
874
857
  updateListItems(updates) {
858
+ if (updates.length > 0) {
859
+ const patched = [...this.items()];
860
+ for (const update of updates) {
861
+ patched[update.index] = update.value;
862
+ }
863
+ this.items.set(patched);
864
+ this.#refreshSelectedTile();
865
+ }
875
866
  this.list().updateListItems(updates);
876
867
  }
877
868
  /**
@@ -889,14 +880,22 @@ class TileListComponent {
889
880
  * @param listItems Updated `DmsObject` instances to apply to the list.
890
881
  */
891
882
  updateTileList(listItems) {
892
- const updates = [];
893
- listItems.forEach((item) => {
883
+ const mappedItems = this.#mapToTileData(listItems);
884
+ const updates = mappedItems
885
+ .map((item) => {
894
886
  const idx = this.items().findIndex((listItem) => listItem.id === item.id);
895
- if (idx >= 0 && this.objectConfig) {
896
- const mappedTileData = this.#mapToTileData([item]);
897
- updates.push({ index: idx, value: mappedTileData[0] });
898
- }
899
- });
887
+ if (idx < 0)
888
+ return undefined;
889
+ const value = {
890
+ ...item,
891
+ actions: (item.actions || [])
892
+ .map((action) => this.#actionService.getActionById(action.id, this.options()?.actionContext))
893
+ .filter((action) => action !== undefined)
894
+ };
895
+ return { index: idx, value };
896
+ })
897
+ .filter((update) => update !== undefined);
898
+ this.#resolveInlineActionsDisabledState(updates.map((u) => u.value));
900
899
  this.updateListItems(updates);
901
900
  }
902
901
  /**
@@ -981,6 +980,38 @@ class TileListComponent {
981
980
  }
982
981
  //#endregion
983
982
  //#region Utilities
983
+ /**
984
+ * Maps `DmsObject` instances to `TileData`, resolves their actions, and updates the
985
+ * internal `items` signal.
986
+ *
987
+ * @param objects `DmsObject` instances to map and update.
988
+ * @returns Array of `TileData` corresponding to the provided `DmsObject` instances.
989
+ */
990
+ #updateItems(objects) {
991
+ const mappedItems = this.#mapToTileData(objects);
992
+ const items = mappedItems.map((item) => ({
993
+ ...item,
994
+ actions: (item.actions || [])
995
+ .map((objectConfigAction) => this.#actionService.getActionById(objectConfigAction.id, this.options()?.actionContext))
996
+ .filter((action) => action !== undefined)
997
+ }));
998
+ this.#resolveInlineActionsDisabledState(items);
999
+ this.items.set([...items, ...this.items()]);
1000
+ return items;
1001
+ }
1002
+ /**
1003
+ * Asynchronously resolves the `disabled` state for inline actions of the given tiles.
1004
+ * Mutates `action.disabled` on the existing action instances and triggers change detection.
1005
+ */
1006
+ #resolveInlineActionsDisabledState(items) {
1007
+ const itemsWithActions = items.filter((item) => item.actions?.length > 0);
1008
+ if (!itemsWithActions.length)
1009
+ return;
1010
+ const resolvers = itemsWithActions.map((item) => this.#actionService.resolveDisabledState(item.actions, [item.dmsObject]));
1011
+ forkJoin(resolvers)
1012
+ .pipe(take(1))
1013
+ .subscribe(() => this.#cdr.markForCheck());
1014
+ }
984
1015
  #getObjectConfig() {
985
1016
  this.#objectConfigService
986
1017
  .getObjectConfigs$(this.bucket() || '', true)
@@ -992,6 +1023,12 @@ class TileListComponent {
992
1023
  }
993
1024
  });
994
1025
  }
1026
+ #refreshSelectedTile() {
1027
+ if (this._selection.length > 0) {
1028
+ const tiles = this._selectionToTileData(this._selection);
1029
+ this.selectedTile.set(tiles);
1030
+ }
1031
+ }
995
1032
  #internalSelectByIndex(idx, evt) {
996
1033
  this.#select(idx, evt?.shiftKey, evt?.ctrlKey);
997
1034
  }
@@ -1013,6 +1050,7 @@ class TileListComponent {
1013
1050
  // skip if selection hasn't changed
1014
1051
  if (this.#isSelectionEqual(sorted))
1015
1052
  return;
1053
+ this.#preselect.set([]);
1016
1054
  this._selection = sorted;
1017
1055
  this._lastSelection = this._selection.length ? this._selection[this._selection.length - 1] : undefined;
1018
1056
  const tiles = this._selectionToTileData(this._selection);
@@ -1059,6 +1097,7 @@ class TileListComponent {
1059
1097
  // skip if selection hasn't changed
1060
1098
  if (this.#isSelectionEqual(newSelection))
1061
1099
  return;
1100
+ this.#preselect.set([]);
1062
1101
  this._selection = newSelection;
1063
1102
  this._lastSelection = this._selection.length === 0 ? undefined : index;
1064
1103
  const tiles = this._selectionToTileData(this._selection);
@@ -1161,7 +1200,7 @@ class TileListComponent {
1161
1200
  #preselectEffect;
1162
1201
  #closeMenuEffect;
1163
1202
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TileListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1164
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: TileListComponent, isStandalone: true, selector: "yuv-tile-list", inputs: { bucket: { classPropertyName: "bucket", publicName: "bucket", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, flavor: { classPropertyName: "flavor", publicName: "flavor", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, preselect: { classPropertyName: "preselect", publicName: "preselect", isSignal: true, isRequired: false, transformFunction: null }, highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: false, transformFunction: null }, preventChangeUntil: { classPropertyName: "preventChangeUntil", publicName: "preventChangeUntil", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, disableCustomContextMenu: { classPropertyName: "disableCustomContextMenu", publicName: "disableCustomContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", tileCopy: "tileCopy", tileCut: "tileCut", busy: "busy", queryResult: "queryResult", selectionChange: "selectionChange", itemDblClick: "itemDblClick", ctxMenu: "ctxMenu" }, host: { listeners: { "keydown.control.c": "onCopy($event)", "keydown.control.x": "onCut($event)" }, properties: { "class.dense": "dense()" } }, providers: [], queries: [{ propertyName: "menuComponent", first: true, predicate: TileActionsMenuComponent, descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "menuTriggers", predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>{{ item.badges }}</ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: YuvListModule }, { kind: "component", type: i2.ListTileComponent, selector: "yuv-list-tile" }, { kind: "ngmodule", type: YuvQueryListModule }, { kind: "component", type: i3.QueryListComponent, selector: "yuv-query-list", inputs: ["query", "idProperty", "transformer", "preventChangeUntil", "autoSelect", "pageSize", "enableDragSelect", "multiselect", "selfHandleSelection", "includePermissions"], outputs: ["itemSelect", "dragSelectChange", "itemDoubleClick", "queryResult"] }, { kind: "directive", type: RendererDirective, selector: "[yuvRenderer]", inputs: ["yuvRenderer"] }, { kind: "directive", type: TileExtensionDirective, selector: "[yuvTileExtension]", inputs: ["yuvTileExtension"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1203
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.20", type: TileListComponent, isStandalone: true, selector: "yuv-tile-list", inputs: { bucket: { classPropertyName: "bucket", publicName: "bucket", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, flavor: { classPropertyName: "flavor", publicName: "flavor", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, preselect: { classPropertyName: "preselect", publicName: "preselect", isSignal: true, isRequired: false, transformFunction: null }, highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: false, transformFunction: null }, preventChangeUntil: { classPropertyName: "preventChangeUntil", publicName: "preventChangeUntil", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, disableCustomContextMenu: { classPropertyName: "disableCustomContextMenu", publicName: "disableCustomContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", tileCopy: "tileCopy", tileCut: "tileCut", busy: "busy", queryResult: "queryResult", selectionChange: "selectionChange", itemDblClick: "itemDblClick", ctxMenu: "ctxMenu" }, host: { listeners: { "keydown.control.c": "onCopy($event)", "keydown.control.x": "onCut($event)" }, properties: { "class.dense": "dense()" } }, providers: [], queries: [{ propertyName: "menuComponent", first: true, predicate: TileActionsMenuComponent, descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "menuTriggers", predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>{{ item.badges }}</ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: YuvListModule }, { kind: "component", type: i2.ListTileComponent, selector: "yuv-list-tile" }, { kind: "ngmodule", type: YuvQueryListModule }, { kind: "component", type: i3.QueryListComponent, selector: "yuv-query-list", inputs: ["query", "idProperty", "transformer", "preventChangeUntil", "autoSelect", "pageSize", "enableDragSelect", "multiselect", "selfHandleSelection", "includePermissions"], outputs: ["itemSelect", "dragSelectChange", "itemDoubleClick", "queryResult"] }, { kind: "directive", type: RendererDirective, selector: "[yuvRenderer]", inputs: ["yuvRenderer"] }, { kind: "directive", type: TileExtensionDirective, selector: "[yuvTileExtension]", inputs: ["yuvTileExtension"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1165
1204
  }
1166
1205
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: TileListComponent, decorators: [{
1167
1206
  type: Component,
@@ -1179,7 +1218,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1179
1218
  '[class.dense]': 'dense()',
1180
1219
  '(keydown.control.c)': 'onCopy($event)',
1181
1220
  '(keydown.control.x)': 'onCut($event)'
1182
- }, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>{{ item.badges }}</ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
1221
+ }, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>{{ item.badges }}</ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
1183
1222
  }], ctorParameters: () => [] });
1184
1223
 
1185
1224
  class ActionSelectComponent {
@@ -1201,34 +1240,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1201
1240
  args: [{ selector: 'yuv-tile-action-select', standalone: true, imports: [NgClass, MatIconModule], template: "<div class=\"actions\">\n @for (a of actions(); track a.id) {\n <button [ngClass]=\"{ selected: selectedActionIds().includes(a.id) }\" (click)=\"actionSelect.emit(a)\">\n <mat-icon>{{ a.icon }}</mat-icon\n >{{ a.label }}\n </button>\n }\n</div>\n", styles: [":host .actions{display:flex;gap:var(--ymt-spacing-xs)}:host .actions button{border:1px solid var(--ymt-outline-variant);border-radius:0;margin-block-end:1px;background-color:var(--mat-sys-secondary-container);color:var(--mat-sys-on-secondary-container);border:0;display:inline-flex;gap:var(--ymt-spacing-xs);padding:var(--ymt-spacing-2xs) var(--ymt-spacing-xs);align-items:center;border-radius:var(--ymt-corner-s)}:host .actions button.selected{background-color:var(--ymt-primary-container);color:var(--ymt-on-primary-container)}\n"] }]
1202
1241
  }] });
1203
1242
 
1204
- class IconSelectComponent {
1205
- constructor() {
1206
- this.objectType = input();
1207
- this.iconSelect = output();
1208
- }
1209
- async createIcon(inputEl) {
1210
- const file = inputEl.files ? inputEl.files[0] : undefined;
1211
- if (file) {
1212
- const text = await file.text();
1213
- this.#emit(text);
1214
- }
1215
- else
1216
- this.#emit(null);
1217
- }
1218
- reset() {
1219
- this.#emit(null);
1220
- }
1221
- #emit(data) {
1222
- this.iconSelect.emit(data);
1223
- }
1224
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: IconSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1225
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.20", type: IconSelectComponent, isStandalone: true, selector: "yuv-icon-select", inputs: { objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { iconSelect: "iconSelect" }, ngImport: i0, template: "<input style=\"display: none\" #fileInput type=\"file\" accept=\".svg\" (change)=\"createIcon(fileInput)\" />\n\n<button class=\"primary\" (click)=\"fileInput.click()\">{{ 'yuv.tile-config.icon-select.pick' | translate }}</button>\n<button class=\"secondary\" (click)=\"reset()\">{{ 'yuv.tile-config.icon-select.reset' | translate }}</button>\n", styles: [":host{display:flex;gap:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] }); }
1226
- }
1227
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: IconSelectComponent, decorators: [{
1228
- type: Component,
1229
- args: [{ selector: 'yuv-icon-select', standalone: true, imports: [CommonModule, TranslateModule], template: "<input style=\"display: none\" #fileInput type=\"file\" accept=\".svg\" (change)=\"createIcon(fileInput)\" />\n\n<button class=\"primary\" (click)=\"fileInput.click()\">{{ 'yuv.tile-config.icon-select.pick' | translate }}</button>\n<button class=\"secondary\" (click)=\"reset()\">{{ 'yuv.tile-config.icon-select.reset' | translate }}</button>\n", styles: [":host{display:flex;gap:var(--ymt-spacing-m)}\n"] }]
1230
- }] });
1231
-
1232
1243
  class PropertySelectComponent {
1233
1244
  constructor() {
1234
1245
  this.system = inject(SystemService);
@@ -1328,6 +1339,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImpo
1328
1339
  args: [{ selector: 'yuv-tile-property-select', standalone: true, imports: [NgClass, FormsModule, TranslateModule, MatButtonModule, MatIconModule], template: "<!-- TODO: enable once filtering of properties makes sense -->\n<!-- <form class=\"filter\">\n <div class=\"filter-input\">\n <input type=\"text\" [placeholder]=\"'yuv.tile-config.property-select.filter.placeholder' | translate\" name=\"query\" [(ngModel)]=\"query\" />\n @if (query()) {\n <button class=\"icn\" (click)=\"query.set(null)\">\n <yuv-icon [svg]=\"clearIcon\"></yuv-icon>\n </button>\n }\n </div>\n</form> -->\n\n<ul class=\"properties\">\n @for (p of filteredObjectTypeFields(); track $index) {\n <li\n tabindex=\"0\"\n [ngClass]=\"{ baseProperty: p.baseProperty, selected: p.id === selectedProperty()?.propertyName }\"\n (click)=\"selectProperty(p)\"\n (keydown.enter)=\"selectPropertyOnKeydown($event, p)\"\n (keydown.space)=\"selectPropertyOnKeydown($event, p)\"\n >\n <div class=\"label\">{{ p.label }}</div>\n <button\n mat-icon-button\n (click)=\"removeProperty($event)\"\n (keydown.enter)=\"removePropertyOnKeydown($event)\"\n (keydown.space)=\"removePropertyOnKeydown($event)\"\n >\n <mat-icon aria-hidden=\"true\" [attr.inert]=\"true\">close</mat-icon>\n </button>\n </li>\n }\n</ul>\n", styles: [":host{display:flex;flex-flow:column;max-height:100%}:host .filter{flex:0 0 auto}:host .filter .filter-input{background-color:var(--ymt-surface-panel);border:1px solid var(--ymt-outline-variant);display:flex;padding:.25em;align-items:center}:host .filter .filter-input input{background-color:transparent;border:0;outline:0;flex:1;color:var(--ymt-text-color)}:host .properties{flex:1;column-count:3;column-width:30ch;column-rule:1px dotted var(--ymt-outline);column-gap:2em;margin-block-start:var(--ymt-spacing-m)}:host .properties li{border:1px solid var(--ymt-outline-variant);border-radius:0;margin-block-end:1px;display:flex;align-items:center;justify-content:space-between;cursor:default}:host .properties li:hover{background-color:var(--ymt-hover-background)}:host .properties li.baseProperty{font-style:italic}:host .properties li.selected{background-color:var(--ymt-primary-container);color:var(--ymt-on-primary-container)}:host .properties li:not(.selected) button{display:none}:host .properties li .label{padding:var(--ymt-spacing-xs) var(--ymt-spacing-m)}:host .properties li button{color:currentColor}\n"] }]
1329
1340
  }] });
1330
1341
 
1342
+ class IconSelectComponent {
1343
+ constructor() {
1344
+ this.objectType = input();
1345
+ this.iconSelect = output();
1346
+ }
1347
+ async createIcon(inputEl) {
1348
+ const file = inputEl.files ? inputEl.files[0] : undefined;
1349
+ if (file) {
1350
+ const text = await file.text();
1351
+ this.#emit(text);
1352
+ }
1353
+ else
1354
+ this.#emit(null);
1355
+ }
1356
+ reset() {
1357
+ this.#emit(null);
1358
+ }
1359
+ #emit(data) {
1360
+ this.iconSelect.emit(data);
1361
+ }
1362
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: IconSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1363
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.20", type: IconSelectComponent, isStandalone: true, selector: "yuv-icon-select", inputs: { objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { iconSelect: "iconSelect" }, ngImport: i0, template: "<input style=\"display: none\" #fileInput type=\"file\" accept=\".svg\" (change)=\"createIcon(fileInput)\" />\n\n<button class=\"primary\" (click)=\"fileInput.click()\">{{ 'yuv.tile-config.icon-select.pick' | translate }}</button>\n<button class=\"secondary\" (click)=\"reset()\">{{ 'yuv.tile-config.icon-select.reset' | translate }}</button>\n", styles: [":host{display:flex;gap:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] }); }
1364
+ }
1365
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.20", ngImport: i0, type: IconSelectComponent, decorators: [{
1366
+ type: Component,
1367
+ args: [{ selector: 'yuv-icon-select', standalone: true, imports: [CommonModule, TranslateModule], template: "<input style=\"display: none\" #fileInput type=\"file\" accept=\".svg\" (change)=\"createIcon(fileInput)\" />\n\n<button class=\"primary\" (click)=\"fileInput.click()\">{{ 'yuv.tile-config.icon-select.pick' | translate }}</button>\n<button class=\"secondary\" (click)=\"reset()\">{{ 'yuv.tile-config.icon-select.reset' | translate }}</button>\n", styles: [":host{display:flex;gap:var(--ymt-spacing-m)}\n"] }]
1368
+ }] });
1369
+
1331
1370
  /**
1332
1371
  * Component for setting up a tile config
1333
1372
  */
@@ -1497,7 +1536,7 @@ class TileConfigComponent {
1497
1536
  label: field.label,
1498
1537
  propertyName: field.id
1499
1538
  }
1500
- : undefined;
1539
+ : null;
1501
1540
  this.objectConfig = structuredClone({
1502
1541
  ...this.objectConfig,
1503
1542
  ...p