@c8y/ngx-components 1024.15.7 → 1024.15.13

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.
@@ -1164,6 +1164,10 @@ class IconSelectorComponent {
1164
1164
  /** When true, displays the icon's CSS class name as a label beneath each tile. */
1165
1165
  this.showIconClass = true;
1166
1166
  this.onSelect = new EventEmitter();
1167
+ /** When true, custom icons are neither loaded from the tenant nor manageable, and only the
1168
+ * built-in icons are shown. Set it for deployments served without a Cumulocity backend,
1169
+ * such as the Codex documentation site. */
1170
+ this.disableCustomIcons = false;
1167
1171
  /** Per-icon labels for tooltips and accessible names. Each takes an `iconName` parameter. */
1168
1172
  this.overriddenIconLabel = gettext('"{{ iconName }}" (overridden)');
1169
1173
  this.iconActionsLabel = gettext('Actions for "{{ iconName }}"');
@@ -1210,7 +1214,7 @@ class IconSelectorComponent {
1210
1214
  // not logged in yet
1211
1215
  }
1212
1216
  const builtInIcons$ = defer(() => from(this.loadBuiltInDefinitions())).pipe(shareReplay({ refCount: true, bufferSize: 1 }));
1213
- const customIcons$ = this.customIconsRefresh$.pipe(map(() => this.registry.toIconDefinitions()),
1217
+ const customIcons$ = this.customIconsRefresh$.pipe(map(() => (this.disableCustomIcons ? [] : this.registry.toIconDefinitions())),
1214
1218
  // Emit an empty list immediately so combineLatest doesn't wait for the
1215
1219
  // registry network fetch before showing built-in icons.
1216
1220
  startWith([]));
@@ -1259,14 +1263,16 @@ class IconSelectorComponent {
1259
1263
  // Only fetch on first open or after a failed load. Skipping on subsequent opens avoids
1260
1264
  // racing against the platform propagating a new activeVersionId after a save.
1261
1265
  // registry.loaded() distinguishes "never loaded / error" from "loaded but empty".
1262
- try {
1263
- if (!this.registry.loaded()) {
1264
- await this.registry.load();
1266
+ if (!this.disableCustomIcons) {
1267
+ try {
1268
+ if (!this.registry.loaded()) {
1269
+ await this.registry.load();
1270
+ }
1271
+ this.syncCustomIconNames();
1272
+ }
1273
+ catch (e) {
1274
+ this.alerts.danger(errorMessage(e, gettext('Failed to load custom icons.')));
1265
1275
  }
1266
- this.syncCustomIconNames();
1267
- }
1268
- catch (e) {
1269
- this.alerts.danger(errorMessage(e, gettext('Failed to load custom icons.')));
1270
1276
  }
1271
1277
  this.customIconsRefresh$.next();
1272
1278
  // iconsLoading is now cleared reactively by tap() in the icons$ pipeline on first emission.
@@ -1497,6 +1503,10 @@ class IconSelectorComponent {
1497
1503
  }
1498
1504
  return matchingCategories;
1499
1505
  }
1506
+ /** Custom icon management requires both the permission and a backend to store the icons in. */
1507
+ get canManageCustomIcons() {
1508
+ return this.isAdmin() && !this.disableCustomIcons;
1509
+ }
1500
1510
  isCustomIcon(iconName) {
1501
1511
  return this.customIconNames().has(iconName);
1502
1512
  }
@@ -1547,7 +1557,7 @@ class IconSelectorComponent {
1547
1557
  URL.revokeObjectURL(url);
1548
1558
  }
1549
1559
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1550
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: IconSelectorComponent, isStandalone: true, selector: "c8y-icon-selector", inputs: { iconCategoriesToExclude: "iconCategoriesToExclude", showIconClass: "showIconClass", selectedIcon: "selectedIcon" }, outputs: { onSelect: "onSelect" }, ngImport: i0, template: "<div\n class=\"p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom sticky-top\"\n style=\"background: var(--c8y-root-component-background-default); z-index: 2\"\n>\n <div class=\"row d-flex-sm\">\n <div class=\"col-sm-5 m-b-8\">\n <div\n class=\"input-group-search input-group\"\n style=\"width: auto\"\n >\n <label\n class=\"sr-only\"\n for=\"filter-icons\"\n translate\n >Filter icons</label\n >\n <input\n class=\"form-control\"\n id=\"filter-icons\"\n placeholder=\"{{ 'Type to filter icons\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"searchTerm$ | async\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n @if (searchTerm$ | async) {\n <button\n class=\"input-group-addon\"\n [attr.aria-label]=\"'Clear search' | translate\"\n type=\"button\"\n (click)=\"onSearchChange('')\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n } @else {\n <span\n class=\"input-group-addon\"\n aria-hidden=\"true\"\n >\n <i\n c8yIcon=\"search\"\n aria-hidden=\"true\"\n ></i>\n </span>\n }\n </div>\n </div>\n <div class=\"col-sm-7 m-b-8\">\n <div class=\"d-flex a-i-center j-c-end gap-16 text-left\">\n <div class=\"d-flex a-i-center flex-grow\">\n <label\n class=\"m-b-0 m-r-8 flex-no-shrink\"\n id=\"icon-category-filter-label\"\n translate\n >Collection</label\n >\n <c8y-select\n class=\"flex-grow\"\n [attr.aria-labelledby]=\"'icon-category-filter-label'\"\n [items]=\"availableIconCategoryItems$ | async\"\n [selected]=\"selectedIconCategory$ | async\"\n [canDeselect]=\"true\"\n (onSelect)=\"onCategoryFilterChanged($any($event).value)\"\n (onDeselect)=\"onCategoryFilterChanged(allIconCategory)\"\n ></c8y-select>\n </div>\n\n @if (isAdmin()) {\n <button\n class=\"btn btn-clean p-l-8 p-r-8 flex-no-shrink\"\n [title]=\"'Add custom icon' | translate\"\n [attr.aria-label]=\"'Add custom icon' | translate\"\n type=\"button\"\n (click)=\"onAddIconClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n <span translate>Add icon</span>\n </button>\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Import icons from ZIP file' | translate\"\n [tooltip]=\"'Import icons from ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onImportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-import\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Import`verb, imports icons from a ZIP file`' | translate }}</span>\n </button>\n @if (hasCustomIcons()) {\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Export custom icons as ZIP file' | translate\"\n [tooltip]=\"'Export custom icons as ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onExportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-export\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Export`verb, exports custom icons as a ZIP file`' | translate }}</span>\n </button>\n }\n }\n </div>\n </div>\n </div>\n\n @if (isSaving()) {\n <div\n class=\"p-absolute m-t-4 p-b-4 overflow-hidden\"\n style=\"left: 0; right: 0\"\n [attr.aria-label]=\"'Saving\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading layout=\"page\"></c8y-loading>\n </div>\n }\n</div>\n\n<div class=\"p-16\">\n @if (iconsLoading()) {\n <div\n class=\"d-flex a-i-center j-c-center p-32\"\n [attr.aria-label]=\"'Loading icons\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading></c8y-loading>\n </div>\n } @else {\n <p\n class=\"sr-only\"\n role=\"status\"\n >\n @if (filteredIconCount() === 0) {\n {{ 'No icons found' | translate }}\n } @else {\n {{ '{{count}} icon(s) found' | translate: { count: filteredIconCount() } }}\n }\n </p>\n <section\n class=\"dtm-icon-grid\"\n [attr.aria-label]=\"'Icon grid' | translate\"\n [attr.aria-busy]=\"visibleDefinitions().length === 0 ? 'true' : null\"\n role=\"region\"\n >\n @for (iconDefinition of visibleDefinitions(); track iconDefinition.label) {\n <div\n class=\"d-contents\"\n [attr.aria-label]=\"iconDefinition.label | translate\"\n role=\"group\"\n >\n <div class=\"legend form-block center grid__col--fullspan d-flex a-i-center gap-8\">\n {{ iconDefinition.label | translate }}\n @if (customCategoryLabels().has(iconDefinition.label)) {\n <span class=\"tag tag--info m-l-4 m-t-0 m-b-0\">{{\n 'Custom`badge indicating a user-added icon category`' | translate\n }}</span>\n }\n </div>\n\n @for (icon of iconDefinition.icons; track icon[0]) {\n @let isCustom = isCustomIcon(icon[0]);\n @let isOverridden = isIconOverridden(icon[0]);\n @let deleteHint = 'Select a different icon before deleting this one.' | translate;\n <div class=\"d-contents\">\n <div\n class=\"dtm-icon-grid__item\"\n [class.dtm-icon-grid__item--selected]=\"selectedIcon && icon[0] === selectedIcon\"\n [class.dtm-icon-grid__item--overridden]=\"isOverridden\"\n >\n <button\n class=\"dtm-icon-grid__btn\"\n [title]=\"icon[0] | iconName\"\n [attr.aria-label]=\"\n isOverridden\n ? (overriddenIconLabel | translate: { iconName: icon[0] | iconName })\n : (icon[0] | iconName)\n \"\n [attr.aria-current]=\"selectedIcon && icon[0] === selectedIcon ? 'true' : null\"\n (click)=\"onIconClicked(icon)\"\n >\n <i\n class=\"icon-40 c8y-icon-duocolor\"\n [c8yIcon]=\"icon[0]\"\n aria-hidden=\"true\"\n ></i>\n @if (showIconClass) {\n <small\n class=\"d-block text-center text-break-word\"\n aria-hidden=\"true\"\n >\n {{ icon[0] | iconName }}\n </small>\n }\n </button>\n\n @if (isOverridden) {\n <span\n class=\"dtm-icon-grid__override-marker\"\n [tooltip]=\"'Overridden icon' | translate\"\n placement=\"top\"\n container=\"body\"\n aria-hidden=\"true\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"replace\"></i>\n </span>\n }\n\n @if (isAdmin()) {\n <div\n class=\"dtm-icon-grid__actions\"\n [attr.aria-label]=\"\n iconActionsLabel | translate: { iconName: icon[0] | iconName }\n \"\n role=\"group\"\n >\n @if (isCustom) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n editIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"editIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onEditIconClicked(icon[0])\"\n >\n <i\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <span\n [tooltip]=\"icon[0] === selectedIcon ? deleteHint : null\"\n placement=\"top\"\n container=\"body\"\n [delay]=\"500\"\n >\n <button\n class=\"btn btn-dot btn-dot--danger m-0\"\n [class.disabled]=\"icon[0] === selectedIcon\"\n [attr.aria-label]=\"\n deleteIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"deleteIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n [attr.aria-disabled]=\"icon[0] === selectedIcon ? 'true' : null\"\n [attr.aria-describedby]=\"\n icon[0] === selectedIcon ? 'delete-hint-' + icon[0] : null\n \"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"\n $event.stopPropagation();\n icon[0] === selectedIcon || onDeleteIconClicked(icon[0])\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (icon[0] === selectedIcon) {\n <span\n class=\"sr-only\"\n [id]=\"'delete-hint-' + icon[0]\"\n >{{ deleteHint }}</span\n >\n }\n </span>\n } @else {\n @let overrideKey = isOverridden ? replaceOverrideLabel : overrideIconLabel;\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n overrideKey | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"overrideKey | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onOverrideIconClicked(icon)\"\n >\n <i\n c8yIcon=\"replace\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (isOverridden) {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.aria-label]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onResetOverrideClicked(icon[0])\"\n >\n <i\n c8yIcon=\"undo\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @empty {\n <c8y-ui-empty-state\n class=\"grid__col--fullspan\"\n icon=\"search\"\n [title]=\"'No icons found' | translate\"\n [subtitle]=\"\n 'Try adjusting your search or filter to find what you\\'re looking for.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n }\n </section>\n }\n <!-- end @else iconsLoading -->\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "component", type: SelectComponent, selector: "c8y-select", inputs: ["placeholder", "items", "selected", "container", "multi", "canSelectWithSpace", "disabled", "autoClose", "insideClick", "required", "canDeselect", "name", "icon", "filterItems"], outputs: ["onSelect", "onDeselect", "onIconClick"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: IconNamePipe, name: "iconName" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1560
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: IconSelectorComponent, isStandalone: true, selector: "c8y-icon-selector", inputs: { iconCategoriesToExclude: "iconCategoriesToExclude", showIconClass: "showIconClass", selectedIcon: "selectedIcon", disableCustomIcons: "disableCustomIcons" }, outputs: { onSelect: "onSelect" }, ngImport: i0, template: "<div\n class=\"p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom sticky-top\"\n style=\"background: var(--c8y-root-component-background-default); z-index: 2\"\n>\n <div class=\"row d-flex-sm\">\n <div class=\"col-sm-5 m-b-8\">\n <div\n class=\"input-group-search input-group\"\n style=\"width: auto\"\n >\n <label\n class=\"sr-only\"\n for=\"filter-icons\"\n translate\n >Filter icons</label\n >\n <input\n class=\"form-control\"\n id=\"filter-icons\"\n placeholder=\"{{ 'Type to filter icons\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"searchTerm$ | async\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n @if (searchTerm$ | async) {\n <button\n class=\"input-group-addon\"\n [attr.aria-label]=\"'Clear search' | translate\"\n type=\"button\"\n (click)=\"onSearchChange('')\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n } @else {\n <span\n class=\"input-group-addon\"\n aria-hidden=\"true\"\n >\n <i\n c8yIcon=\"search\"\n aria-hidden=\"true\"\n ></i>\n </span>\n }\n </div>\n </div>\n <div class=\"col-sm-7 m-b-8\">\n <div class=\"d-flex a-i-center j-c-end gap-16 text-left\">\n <div class=\"d-flex a-i-center flex-grow\">\n <label\n class=\"m-b-0 m-r-8 flex-no-shrink\"\n id=\"icon-category-filter-label\"\n translate\n >Collection</label\n >\n <c8y-select\n class=\"flex-grow\"\n [attr.aria-labelledby]=\"'icon-category-filter-label'\"\n [items]=\"availableIconCategoryItems$ | async\"\n [selected]=\"selectedIconCategory$ | async\"\n [canDeselect]=\"true\"\n (onSelect)=\"onCategoryFilterChanged($any($event).value)\"\n (onDeselect)=\"onCategoryFilterChanged(allIconCategory)\"\n ></c8y-select>\n </div>\n\n @if (canManageCustomIcons) {\n <button\n class=\"btn btn-clean p-l-8 p-r-8 flex-no-shrink\"\n [title]=\"'Add custom icon' | translate\"\n [attr.aria-label]=\"'Add custom icon' | translate\"\n type=\"button\"\n (click)=\"onAddIconClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n <span translate>Add icon</span>\n </button>\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Import icons from ZIP file' | translate\"\n [tooltip]=\"'Import icons from ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onImportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-import\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Import`verb, imports icons from a ZIP file`' | translate }}</span>\n </button>\n @if (hasCustomIcons()) {\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Export custom icons as ZIP file' | translate\"\n [tooltip]=\"'Export custom icons as ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onExportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-export\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Export`verb, exports custom icons as a ZIP file`' | translate }}</span>\n </button>\n }\n }\n </div>\n </div>\n </div>\n\n @if (isSaving()) {\n <div\n class=\"p-absolute m-t-4 p-b-4 overflow-hidden\"\n style=\"left: 0; right: 0\"\n [attr.aria-label]=\"'Saving\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading layout=\"page\"></c8y-loading>\n </div>\n }\n</div>\n\n<div class=\"p-16\">\n @if (iconsLoading()) {\n <div\n class=\"d-flex a-i-center j-c-center p-32\"\n [attr.aria-label]=\"'Loading icons\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading></c8y-loading>\n </div>\n } @else {\n <p\n class=\"sr-only\"\n role=\"status\"\n >\n @if (filteredIconCount() === 0) {\n {{ 'No icons found' | translate }}\n } @else {\n {{ '{{count}} icon(s) found' | translate: { count: filteredIconCount() } }}\n }\n </p>\n <section\n class=\"dtm-icon-grid\"\n [attr.aria-label]=\"'Icon grid' | translate\"\n [attr.aria-busy]=\"visibleDefinitions().length === 0 ? 'true' : null\"\n role=\"region\"\n >\n @for (iconDefinition of visibleDefinitions(); track iconDefinition.label) {\n <div\n class=\"d-contents\"\n [attr.aria-label]=\"iconDefinition.label | translate\"\n role=\"group\"\n >\n <div class=\"legend form-block center grid__col--fullspan d-flex a-i-center gap-8\">\n {{ iconDefinition.label | translate }}\n @if (customCategoryLabels().has(iconDefinition.label)) {\n <span class=\"tag tag--info m-l-4 m-t-0 m-b-0\">{{\n 'Custom`badge indicating a user-added icon category`' | translate\n }}</span>\n }\n </div>\n\n @for (icon of iconDefinition.icons; track icon[0]) {\n @let isCustom = isCustomIcon(icon[0]);\n @let isOverridden = isIconOverridden(icon[0]);\n @let deleteHint = 'Select a different icon before deleting this one.' | translate;\n <div class=\"d-contents\">\n <div\n class=\"dtm-icon-grid__item\"\n [class.dtm-icon-grid__item--selected]=\"selectedIcon && icon[0] === selectedIcon\"\n [class.dtm-icon-grid__item--overridden]=\"isOverridden\"\n >\n <button\n class=\"dtm-icon-grid__btn\"\n [title]=\"icon[0] | iconName\"\n [attr.aria-label]=\"\n isOverridden\n ? (overriddenIconLabel | translate: { iconName: icon[0] | iconName })\n : (icon[0] | iconName)\n \"\n [attr.aria-current]=\"selectedIcon && icon[0] === selectedIcon ? 'true' : null\"\n (click)=\"onIconClicked(icon)\"\n >\n <i\n class=\"icon-40 c8y-icon-duocolor\"\n [c8yIcon]=\"icon[0]\"\n aria-hidden=\"true\"\n ></i>\n @if (showIconClass) {\n <small\n class=\"d-block text-center text-break-word\"\n aria-hidden=\"true\"\n >\n {{ icon[0] | iconName }}\n </small>\n }\n </button>\n\n @if (isOverridden) {\n <span\n class=\"dtm-icon-grid__override-marker\"\n [tooltip]=\"'Overridden icon' | translate\"\n placement=\"top\"\n container=\"body\"\n aria-hidden=\"true\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"replace\"></i>\n </span>\n }\n\n @if (canManageCustomIcons) {\n <div\n class=\"dtm-icon-grid__actions\"\n [attr.aria-label]=\"\n iconActionsLabel | translate: { iconName: icon[0] | iconName }\n \"\n role=\"group\"\n >\n @if (isCustom) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n editIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"editIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onEditIconClicked(icon[0])\"\n >\n <i\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <span\n [tooltip]=\"icon[0] === selectedIcon ? deleteHint : null\"\n placement=\"top\"\n container=\"body\"\n [delay]=\"500\"\n >\n <button\n class=\"btn btn-dot btn-dot--danger m-0\"\n [class.disabled]=\"icon[0] === selectedIcon\"\n [attr.aria-label]=\"\n deleteIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"deleteIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n [attr.aria-disabled]=\"icon[0] === selectedIcon ? 'true' : null\"\n [attr.aria-describedby]=\"\n icon[0] === selectedIcon ? 'delete-hint-' + icon[0] : null\n \"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"\n $event.stopPropagation();\n icon[0] === selectedIcon || onDeleteIconClicked(icon[0])\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (icon[0] === selectedIcon) {\n <span\n class=\"sr-only\"\n [id]=\"'delete-hint-' + icon[0]\"\n >{{ deleteHint }}</span\n >\n }\n </span>\n } @else {\n @let overrideKey = isOverridden ? replaceOverrideLabel : overrideIconLabel;\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n overrideKey | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"overrideKey | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onOverrideIconClicked(icon)\"\n >\n <i\n c8yIcon=\"replace\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (isOverridden) {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.aria-label]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onResetOverrideClicked(icon[0])\"\n >\n <i\n c8yIcon=\"undo\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @empty {\n <c8y-ui-empty-state\n class=\"grid__col--fullspan\"\n icon=\"search\"\n [title]=\"'No icons found' | translate\"\n [subtitle]=\"\n 'Try adjusting your search or filter to find what you\\'re looking for.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n }\n </section>\n }\n <!-- end @else iconsLoading -->\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "component", type: SelectComponent, selector: "c8y-select", inputs: ["placeholder", "items", "selected", "container", "multi", "canSelectWithSpace", "disabled", "autoClose", "insideClick", "required", "canDeselect", "name", "icon", "filterItems"], outputs: ["onSelect", "onDeselect", "onIconClick"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: IconNamePipe, name: "iconName" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1551
1561
  }
1552
1562
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconSelectorComponent, decorators: [{
1553
1563
  type: Component,
@@ -1562,7 +1572,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
1562
1572
  LoadingComponent,
1563
1573
  SelectComponent,
1564
1574
  TooltipModule
1565
- ], template: "<div\n class=\"p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom sticky-top\"\n style=\"background: var(--c8y-root-component-background-default); z-index: 2\"\n>\n <div class=\"row d-flex-sm\">\n <div class=\"col-sm-5 m-b-8\">\n <div\n class=\"input-group-search input-group\"\n style=\"width: auto\"\n >\n <label\n class=\"sr-only\"\n for=\"filter-icons\"\n translate\n >Filter icons</label\n >\n <input\n class=\"form-control\"\n id=\"filter-icons\"\n placeholder=\"{{ 'Type to filter icons\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"searchTerm$ | async\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n @if (searchTerm$ | async) {\n <button\n class=\"input-group-addon\"\n [attr.aria-label]=\"'Clear search' | translate\"\n type=\"button\"\n (click)=\"onSearchChange('')\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n } @else {\n <span\n class=\"input-group-addon\"\n aria-hidden=\"true\"\n >\n <i\n c8yIcon=\"search\"\n aria-hidden=\"true\"\n ></i>\n </span>\n }\n </div>\n </div>\n <div class=\"col-sm-7 m-b-8\">\n <div class=\"d-flex a-i-center j-c-end gap-16 text-left\">\n <div class=\"d-flex a-i-center flex-grow\">\n <label\n class=\"m-b-0 m-r-8 flex-no-shrink\"\n id=\"icon-category-filter-label\"\n translate\n >Collection</label\n >\n <c8y-select\n class=\"flex-grow\"\n [attr.aria-labelledby]=\"'icon-category-filter-label'\"\n [items]=\"availableIconCategoryItems$ | async\"\n [selected]=\"selectedIconCategory$ | async\"\n [canDeselect]=\"true\"\n (onSelect)=\"onCategoryFilterChanged($any($event).value)\"\n (onDeselect)=\"onCategoryFilterChanged(allIconCategory)\"\n ></c8y-select>\n </div>\n\n @if (isAdmin()) {\n <button\n class=\"btn btn-clean p-l-8 p-r-8 flex-no-shrink\"\n [title]=\"'Add custom icon' | translate\"\n [attr.aria-label]=\"'Add custom icon' | translate\"\n type=\"button\"\n (click)=\"onAddIconClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n <span translate>Add icon</span>\n </button>\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Import icons from ZIP file' | translate\"\n [tooltip]=\"'Import icons from ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onImportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-import\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Import`verb, imports icons from a ZIP file`' | translate }}</span>\n </button>\n @if (hasCustomIcons()) {\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Export custom icons as ZIP file' | translate\"\n [tooltip]=\"'Export custom icons as ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onExportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-export\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Export`verb, exports custom icons as a ZIP file`' | translate }}</span>\n </button>\n }\n }\n </div>\n </div>\n </div>\n\n @if (isSaving()) {\n <div\n class=\"p-absolute m-t-4 p-b-4 overflow-hidden\"\n style=\"left: 0; right: 0\"\n [attr.aria-label]=\"'Saving\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading layout=\"page\"></c8y-loading>\n </div>\n }\n</div>\n\n<div class=\"p-16\">\n @if (iconsLoading()) {\n <div\n class=\"d-flex a-i-center j-c-center p-32\"\n [attr.aria-label]=\"'Loading icons\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading></c8y-loading>\n </div>\n } @else {\n <p\n class=\"sr-only\"\n role=\"status\"\n >\n @if (filteredIconCount() === 0) {\n {{ 'No icons found' | translate }}\n } @else {\n {{ '{{count}} icon(s) found' | translate: { count: filteredIconCount() } }}\n }\n </p>\n <section\n class=\"dtm-icon-grid\"\n [attr.aria-label]=\"'Icon grid' | translate\"\n [attr.aria-busy]=\"visibleDefinitions().length === 0 ? 'true' : null\"\n role=\"region\"\n >\n @for (iconDefinition of visibleDefinitions(); track iconDefinition.label) {\n <div\n class=\"d-contents\"\n [attr.aria-label]=\"iconDefinition.label | translate\"\n role=\"group\"\n >\n <div class=\"legend form-block center grid__col--fullspan d-flex a-i-center gap-8\">\n {{ iconDefinition.label | translate }}\n @if (customCategoryLabels().has(iconDefinition.label)) {\n <span class=\"tag tag--info m-l-4 m-t-0 m-b-0\">{{\n 'Custom`badge indicating a user-added icon category`' | translate\n }}</span>\n }\n </div>\n\n @for (icon of iconDefinition.icons; track icon[0]) {\n @let isCustom = isCustomIcon(icon[0]);\n @let isOverridden = isIconOverridden(icon[0]);\n @let deleteHint = 'Select a different icon before deleting this one.' | translate;\n <div class=\"d-contents\">\n <div\n class=\"dtm-icon-grid__item\"\n [class.dtm-icon-grid__item--selected]=\"selectedIcon && icon[0] === selectedIcon\"\n [class.dtm-icon-grid__item--overridden]=\"isOverridden\"\n >\n <button\n class=\"dtm-icon-grid__btn\"\n [title]=\"icon[0] | iconName\"\n [attr.aria-label]=\"\n isOverridden\n ? (overriddenIconLabel | translate: { iconName: icon[0] | iconName })\n : (icon[0] | iconName)\n \"\n [attr.aria-current]=\"selectedIcon && icon[0] === selectedIcon ? 'true' : null\"\n (click)=\"onIconClicked(icon)\"\n >\n <i\n class=\"icon-40 c8y-icon-duocolor\"\n [c8yIcon]=\"icon[0]\"\n aria-hidden=\"true\"\n ></i>\n @if (showIconClass) {\n <small\n class=\"d-block text-center text-break-word\"\n aria-hidden=\"true\"\n >\n {{ icon[0] | iconName }}\n </small>\n }\n </button>\n\n @if (isOverridden) {\n <span\n class=\"dtm-icon-grid__override-marker\"\n [tooltip]=\"'Overridden icon' | translate\"\n placement=\"top\"\n container=\"body\"\n aria-hidden=\"true\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"replace\"></i>\n </span>\n }\n\n @if (isAdmin()) {\n <div\n class=\"dtm-icon-grid__actions\"\n [attr.aria-label]=\"\n iconActionsLabel | translate: { iconName: icon[0] | iconName }\n \"\n role=\"group\"\n >\n @if (isCustom) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n editIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"editIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onEditIconClicked(icon[0])\"\n >\n <i\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <span\n [tooltip]=\"icon[0] === selectedIcon ? deleteHint : null\"\n placement=\"top\"\n container=\"body\"\n [delay]=\"500\"\n >\n <button\n class=\"btn btn-dot btn-dot--danger m-0\"\n [class.disabled]=\"icon[0] === selectedIcon\"\n [attr.aria-label]=\"\n deleteIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"deleteIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n [attr.aria-disabled]=\"icon[0] === selectedIcon ? 'true' : null\"\n [attr.aria-describedby]=\"\n icon[0] === selectedIcon ? 'delete-hint-' + icon[0] : null\n \"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"\n $event.stopPropagation();\n icon[0] === selectedIcon || onDeleteIconClicked(icon[0])\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (icon[0] === selectedIcon) {\n <span\n class=\"sr-only\"\n [id]=\"'delete-hint-' + icon[0]\"\n >{{ deleteHint }}</span\n >\n }\n </span>\n } @else {\n @let overrideKey = isOverridden ? replaceOverrideLabel : overrideIconLabel;\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n overrideKey | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"overrideKey | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onOverrideIconClicked(icon)\"\n >\n <i\n c8yIcon=\"replace\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (isOverridden) {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.aria-label]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onResetOverrideClicked(icon[0])\"\n >\n <i\n c8yIcon=\"undo\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @empty {\n <c8y-ui-empty-state\n class=\"grid__col--fullspan\"\n icon=\"search\"\n [title]=\"'No icons found' | translate\"\n [subtitle]=\"\n 'Try adjusting your search or filter to find what you\\'re looking for.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n }\n </section>\n }\n <!-- end @else iconsLoading -->\n</div>\n" }]
1575
+ ], template: "<div\n class=\"p-l-24 p-r-24 p-t-8 p-b-8 separator-bottom sticky-top\"\n style=\"background: var(--c8y-root-component-background-default); z-index: 2\"\n>\n <div class=\"row d-flex-sm\">\n <div class=\"col-sm-5 m-b-8\">\n <div\n class=\"input-group-search input-group\"\n style=\"width: auto\"\n >\n <label\n class=\"sr-only\"\n for=\"filter-icons\"\n translate\n >Filter icons</label\n >\n <input\n class=\"form-control\"\n id=\"filter-icons\"\n placeholder=\"{{ 'Type to filter icons\u2026' | translate }}\"\n type=\"search\"\n [ngModel]=\"searchTerm$ | async\"\n (ngModelChange)=\"onSearchChange($event)\"\n />\n @if (searchTerm$ | async) {\n <button\n class=\"input-group-addon\"\n [attr.aria-label]=\"'Clear search' | translate\"\n type=\"button\"\n (click)=\"onSearchChange('')\"\n >\n <i\n c8yIcon=\"times\"\n aria-hidden=\"true\"\n ></i>\n </button>\n } @else {\n <span\n class=\"input-group-addon\"\n aria-hidden=\"true\"\n >\n <i\n c8yIcon=\"search\"\n aria-hidden=\"true\"\n ></i>\n </span>\n }\n </div>\n </div>\n <div class=\"col-sm-7 m-b-8\">\n <div class=\"d-flex a-i-center j-c-end gap-16 text-left\">\n <div class=\"d-flex a-i-center flex-grow\">\n <label\n class=\"m-b-0 m-r-8 flex-no-shrink\"\n id=\"icon-category-filter-label\"\n translate\n >Collection</label\n >\n <c8y-select\n class=\"flex-grow\"\n [attr.aria-labelledby]=\"'icon-category-filter-label'\"\n [items]=\"availableIconCategoryItems$ | async\"\n [selected]=\"selectedIconCategory$ | async\"\n [canDeselect]=\"true\"\n (onSelect)=\"onCategoryFilterChanged($any($event).value)\"\n (onDeselect)=\"onCategoryFilterChanged(allIconCategory)\"\n ></c8y-select>\n </div>\n\n @if (canManageCustomIcons) {\n <button\n class=\"btn btn-clean p-l-8 p-r-8 flex-no-shrink\"\n [title]=\"'Add custom icon' | translate\"\n [attr.aria-label]=\"'Add custom icon' | translate\"\n type=\"button\"\n (click)=\"onAddIconClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"plus-circle\"\n aria-hidden=\"true\"\n ></i>\n <span translate>Add icon</span>\n </button>\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Import icons from ZIP file' | translate\"\n [tooltip]=\"'Import icons from ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onImportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-import\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Import`verb, imports icons from a ZIP file`' | translate }}</span>\n </button>\n @if (hasCustomIcons()) {\n <button\n class=\"btn btn-clean flex-no-shrink\"\n [attr.aria-label]=\"'Export custom icons as ZIP file' | translate\"\n [tooltip]=\"'Export custom icons as ZIP file' | translate\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n [adaptivePosition]=\"false\"\n (click)=\"onExportClicked()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"data-export\"\n aria-hidden=\"true\"\n ></i>\n <span>{{ 'Export`verb, exports custom icons as a ZIP file`' | translate }}</span>\n </button>\n }\n }\n </div>\n </div>\n </div>\n\n @if (isSaving()) {\n <div\n class=\"p-absolute m-t-4 p-b-4 overflow-hidden\"\n style=\"left: 0; right: 0\"\n [attr.aria-label]=\"'Saving\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading layout=\"page\"></c8y-loading>\n </div>\n }\n</div>\n\n<div class=\"p-16\">\n @if (iconsLoading()) {\n <div\n class=\"d-flex a-i-center j-c-center p-32\"\n [attr.aria-label]=\"'Loading icons\u2026' | translate\"\n role=\"status\"\n >\n <c8y-loading></c8y-loading>\n </div>\n } @else {\n <p\n class=\"sr-only\"\n role=\"status\"\n >\n @if (filteredIconCount() === 0) {\n {{ 'No icons found' | translate }}\n } @else {\n {{ '{{count}} icon(s) found' | translate: { count: filteredIconCount() } }}\n }\n </p>\n <section\n class=\"dtm-icon-grid\"\n [attr.aria-label]=\"'Icon grid' | translate\"\n [attr.aria-busy]=\"visibleDefinitions().length === 0 ? 'true' : null\"\n role=\"region\"\n >\n @for (iconDefinition of visibleDefinitions(); track iconDefinition.label) {\n <div\n class=\"d-contents\"\n [attr.aria-label]=\"iconDefinition.label | translate\"\n role=\"group\"\n >\n <div class=\"legend form-block center grid__col--fullspan d-flex a-i-center gap-8\">\n {{ iconDefinition.label | translate }}\n @if (customCategoryLabels().has(iconDefinition.label)) {\n <span class=\"tag tag--info m-l-4 m-t-0 m-b-0\">{{\n 'Custom`badge indicating a user-added icon category`' | translate\n }}</span>\n }\n </div>\n\n @for (icon of iconDefinition.icons; track icon[0]) {\n @let isCustom = isCustomIcon(icon[0]);\n @let isOverridden = isIconOverridden(icon[0]);\n @let deleteHint = 'Select a different icon before deleting this one.' | translate;\n <div class=\"d-contents\">\n <div\n class=\"dtm-icon-grid__item\"\n [class.dtm-icon-grid__item--selected]=\"selectedIcon && icon[0] === selectedIcon\"\n [class.dtm-icon-grid__item--overridden]=\"isOverridden\"\n >\n <button\n class=\"dtm-icon-grid__btn\"\n [title]=\"icon[0] | iconName\"\n [attr.aria-label]=\"\n isOverridden\n ? (overriddenIconLabel | translate: { iconName: icon[0] | iconName })\n : (icon[0] | iconName)\n \"\n [attr.aria-current]=\"selectedIcon && icon[0] === selectedIcon ? 'true' : null\"\n (click)=\"onIconClicked(icon)\"\n >\n <i\n class=\"icon-40 c8y-icon-duocolor\"\n [c8yIcon]=\"icon[0]\"\n aria-hidden=\"true\"\n ></i>\n @if (showIconClass) {\n <small\n class=\"d-block text-center text-break-word\"\n aria-hidden=\"true\"\n >\n {{ icon[0] | iconName }}\n </small>\n }\n </button>\n\n @if (isOverridden) {\n <span\n class=\"dtm-icon-grid__override-marker\"\n [tooltip]=\"'Overridden icon' | translate\"\n placement=\"top\"\n container=\"body\"\n aria-hidden=\"true\"\n [delay]=\"500\"\n >\n <i c8yIcon=\"replace\"></i>\n </span>\n }\n\n @if (canManageCustomIcons) {\n <div\n class=\"dtm-icon-grid__actions\"\n [attr.aria-label]=\"\n iconActionsLabel | translate: { iconName: icon[0] | iconName }\n \"\n role=\"group\"\n >\n @if (isCustom) {\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n editIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"editIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onEditIconClicked(icon[0])\"\n >\n <i\n c8yIcon=\"pencil\"\n aria-hidden=\"true\"\n ></i>\n </button>\n <span\n [tooltip]=\"icon[0] === selectedIcon ? deleteHint : null\"\n placement=\"top\"\n container=\"body\"\n [delay]=\"500\"\n >\n <button\n class=\"btn btn-dot btn-dot--danger m-0\"\n [class.disabled]=\"icon[0] === selectedIcon\"\n [attr.aria-label]=\"\n deleteIconLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"deleteIconLabel | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n [attr.aria-disabled]=\"icon[0] === selectedIcon ? 'true' : null\"\n [attr.aria-describedby]=\"\n icon[0] === selectedIcon ? 'delete-hint-' + icon[0] : null\n \"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"\n $event.stopPropagation();\n icon[0] === selectedIcon || onDeleteIconClicked(icon[0])\n \"\n >\n <i\n c8yIcon=\"minus-circle\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (icon[0] === selectedIcon) {\n <span\n class=\"sr-only\"\n [id]=\"'delete-hint-' + icon[0]\"\n >{{ deleteHint }}</span\n >\n }\n </span>\n } @else {\n @let overrideKey = isOverridden ? replaceOverrideLabel : overrideIconLabel;\n <button\n class=\"btn btn-dot\"\n [attr.aria-label]=\"\n overrideKey | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"overrideKey | translate: { iconName: icon[0] | iconName }\"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onOverrideIconClicked(icon)\"\n >\n <i\n c8yIcon=\"replace\"\n aria-hidden=\"true\"\n ></i>\n </button>\n @if (isOverridden) {\n <button\n class=\"btn btn-dot btn-dot--danger\"\n [attr.aria-label]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n [tooltip]=\"\n resetOverrideLabel | translate: { iconName: icon[0] | iconName }\n \"\n placement=\"top\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"$event.stopPropagation(); onResetOverrideClicked(icon[0])\"\n >\n <i\n c8yIcon=\"undo\"\n aria-hidden=\"true\"\n ></i>\n </button>\n }\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @empty {\n <c8y-ui-empty-state\n class=\"grid__col--fullspan\"\n icon=\"search\"\n [title]=\"'No icons found' | translate\"\n [subtitle]=\"\n 'Try adjusting your search or filter to find what you\\'re looking for.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n }\n </section>\n }\n <!-- end @else iconsLoading -->\n</div>\n" }]
1566
1576
  }], ctorParameters: () => [], propDecorators: { iconCategoriesToExclude: [{
1567
1577
  type: Input
1568
1578
  }], showIconClass: [{
@@ -1571,6 +1581,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
1571
1581
  type: Output
1572
1582
  }], selectedIcon: [{
1573
1583
  type: Input
1584
+ }], disableCustomIcons: [{
1585
+ type: Input
1574
1586
  }] } });
1575
1587
 
1576
1588
  class IconSelectorModalComponent {
@@ -1603,7 +1615,7 @@ class IconSelectorModalComponent {
1603
1615
  this.cdr.markForCheck();
1604
1616
  }
1605
1617
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconSelectorModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1606
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: IconSelectorModalComponent, isStandalone: true, selector: "c8y-icon-selector-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"title | translate\"\n (onDismiss)=\"close()\"\n (onClose)=\"saveChanges()\"\n headerClasses=\"text-center\"\n [disabled]=\"!selectionExplicitlySet\"\n [labels]=\"{ cancel: 'Cancel', ok: saveButtonLabel | translate }\"\n>\n <c8y-icon-selector\n [selectedIcon]=\"currentSelection\"\n [iconCategoriesToExclude]=\"iconCategoriesToExclude\"\n [showIconClass]=\"showIconClass\"\n (onSelect)=\"selectionChange($event)\"\n ></c8y-icon-selector>\n</c8y-modal>\n", dependencies: [{ kind: "component", type: IconSelectorComponent, selector: "c8y-icon-selector", inputs: ["iconCategoriesToExclude", "showIconClass", "selectedIcon"], outputs: ["onSelect"] }, { kind: "component", type: ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1618
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: IconSelectorModalComponent, isStandalone: true, selector: "c8y-icon-selector-modal", ngImport: i0, template: "<c8y-modal\n [title]=\"title | translate\"\n (onDismiss)=\"close()\"\n (onClose)=\"saveChanges()\"\n headerClasses=\"text-center\"\n [disabled]=\"!selectionExplicitlySet\"\n [labels]=\"{ cancel: 'Cancel', ok: saveButtonLabel | translate }\"\n>\n <c8y-icon-selector\n [selectedIcon]=\"currentSelection\"\n [iconCategoriesToExclude]=\"iconCategoriesToExclude\"\n [showIconClass]=\"showIconClass\"\n (onSelect)=\"selectionChange($event)\"\n ></c8y-icon-selector>\n</c8y-modal>\n", dependencies: [{ kind: "component", type: IconSelectorComponent, selector: "c8y-icon-selector", inputs: ["iconCategoriesToExclude", "showIconClass", "selectedIcon", "disableCustomIcons"], outputs: ["onSelect"] }, { kind: "component", type: ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1607
1619
  }
1608
1620
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: IconSelectorModalComponent, decorators: [{
1609
1621
  type: Component,