@c8y/ngx-components 1023.15.0 → 1023.16.3

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.
@@ -4,7 +4,7 @@ import * as i1$4 from 'ngx-bootstrap/dropdown';
4
4
  import { BsDropdownModule, BsDropdownDirective } from 'ngx-bootstrap/dropdown';
5
5
  import { CdkTrapFocus, A11yModule } from '@angular/cdk/a11y';
6
6
  import { castArray, flatten, uniq, sortBy, groupBy, camelCase, isEqual, isUndefined, throttle as throttle$1, each, mapValues, mapKeys, keys, get, isNaN as isNaN$1, isFinite, forEach, assign, min, every, first, map as map$1, find, negate, upperFirst, memoize as memoize$1, isEmpty, property, some, entries, omitBy, isDate, pick, flatMap, cloneDeep, set as set$1, orderBy, filter as filter$2, snakeCase, matches, escape, escapeRegExp, assignWith, uniqBy, toNumber, isEqualWith, clone, omit, has, transform, identity, unset, flow, findIndex as findIndex$1, isNil, chunk, values, union, without, indexOf, kebabCase, forOwn } from 'lodash-es';
7
- import { merge, of, defer, combineLatest, race, isObservable, from, Subject, BehaviorSubject, ReplaySubject, firstValueFrom, lastValueFrom, NEVER, Observable, startWith as startWith$1, filter as filter$1, tap as tap$1, mergeMap, fromEvent, pipe, throwError, concat, map as map$2, timer, fromEventPattern, withLatestFrom, distinctUntilChanged as distinctUntilChanged$1, takeUntil as takeUntil$1, switchMap as switchMap$1, shareReplay as shareReplay$1, catchError as catchError$1, empty, forkJoin, interval } from 'rxjs';
7
+ import { merge, of, defer, combineLatest, race, isObservable, from, Subject, BehaviorSubject, ReplaySubject, firstValueFrom, lastValueFrom, NEVER, Observable, startWith as startWith$1, filter as filter$1, tap as tap$1, mergeMap, fromEvent, pipe, throwError, concat, map as map$2, timer, fromEventPattern, withLatestFrom, distinctUntilChanged as distinctUntilChanged$1, takeUntil as takeUntil$1, switchMap as switchMap$1, shareReplay as shareReplay$1, catchError as catchError$1, empty, forkJoin, interval, skip as skip$1, debounceTime as debounceTime$1 } from 'rxjs';
8
8
  import { map, distinctUntilChanged, filter, startWith, switchMap, shareReplay, take, scan, takeUntil, tap, catchError, debounceTime, share, first as first$1, retryWhen, delay, concatMap, mergeMap as mergeMap$1, debounce, sample, withLatestFrom as withLatestFrom$1, every as every$1, toArray, merge as merge$1, expand, mapTo, skip, reduce, finalize, combineLatestWith } from 'rxjs/operators';
9
9
  import * as i1 from '@c8y/client';
10
10
  import { InventoryService, OperationStatus, TenantLoginOptionType, UserManagementSource, GrantType, ApplicationType, BasicAuth, CookieAuth, Realtime, FetchClient, BearerAuthFromSessionStorage, FeatureService, ApplicationAvailability, QueriesUtil, Client, PasswordStrength, AlarmService, TenantService, ApplicationService, UserService, aggregationType, Service, Paging } from '@c8y/client';
@@ -2971,6 +2971,18 @@ const MESSAGES_CORE_I18N = {
2971
2971
  placeholders: {
2972
2972
  revokedSerials: '$1'
2973
2973
  }
2974
+ },
2975
+ "^Certificate serial number hex: '(.+?)'.*$": {
2976
+ gettext: gettext$1('Certificate serial number: "{{ serialNumber }}"'),
2977
+ placeholders: {
2978
+ serialNumber: '$1'
2979
+ }
2980
+ },
2981
+ '^Tenant certificate authority\\(CA\\) signed certificate for device: (.+?)\\.$': {
2982
+ gettext: gettext$1('Tenant certificate authority (CA) signed certificate for device: "{{ deviceId }}".'),
2983
+ placeholders: {
2984
+ deviceId: '$1'
2985
+ }
2974
2986
  }
2975
2987
  };
2976
2988
 
@@ -8805,6 +8817,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
8805
8817
  }]
8806
8818
  }] });
8807
8819
 
8820
+ /**
8821
+ * Pipe that strips HTML tags from a string.
8822
+ *
8823
+ * Useful for creating plain text versions of HTML content,
8824
+ * such as for aria-labels or other accessibility attributes.
8825
+ *
8826
+ * @example
8827
+ * ```html
8828
+ * <div [attr.aria-label]="htmlContent | stripHtml">
8829
+ * <div [innerHTML]="htmlContent"></div>
8830
+ * </div>
8831
+ * ```
8832
+ *
8833
+ * @example
8834
+ * ```typescript
8835
+ * const html = '<p>Hello <strong>world</strong></p>';
8836
+ * // Result: 'Hello world'
8837
+ * ```
8838
+ */
8839
+ class StripHtmlPipe {
8840
+ /**
8841
+ * Strips HTML tags from the input string.
8842
+ *
8843
+ * @param value - The HTML string to process
8844
+ * @returns Plain text with HTML tags removed
8845
+ */
8846
+ transform(value) {
8847
+ if (!value) {
8848
+ return '';
8849
+ }
8850
+ const tmp = document.createElement('div');
8851
+ tmp.innerHTML = value;
8852
+ return tmp.textContent || tmp.innerText || '';
8853
+ }
8854
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: StripHtmlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
8855
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.15", ngImport: i0, type: StripHtmlPipe, isStandalone: true, name: "stripHtml" }); }
8856
+ }
8857
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: StripHtmlPipe, decorators: [{
8858
+ type: Pipe,
8859
+ args: [{
8860
+ name: 'stripHtml',
8861
+ standalone: true,
8862
+ pure: true
8863
+ }]
8864
+ }] });
8865
+
8866
+ /**
8867
+ * Icon Panel Component
8868
+ *
8869
+ * Displays information in a grid of bordered panels, each with an icon, label, and content.
8870
+ * Useful for showing structured metadata, device information, connection status, etc.
8871
+ *
8872
+ * @example
8873
+ * ```typescript
8874
+ * sections: IconPanelSection[] = [
8875
+ * {
8876
+ * id: 'device-info',
8877
+ * label: 'Device Information',
8878
+ * icon: 'c8y-device',
8879
+ * visible: true,
8880
+ * content: '<p>Device ID: THM-001</p><p>Type: Sensor</p>',
8881
+ * colClass: 'col-xs-12 col-md-6'
8882
+ * },
8883
+ * {
8884
+ * id: 'status',
8885
+ * label: 'Status',
8886
+ * icon: 'c8y-connection',
8887
+ * visible: true,
8888
+ * content: 'Connected',
8889
+ * colClass: 'col-xs-12 col-md-6'
8890
+ * }
8891
+ * ];
8892
+ * ```
8893
+ *
8894
+ * ```html
8895
+ * <c8y-icon-panel [sections]="sections"></c8y-icon-panel>
8896
+ * ```
8897
+ *
8898
+ * You can also project additional content:
8899
+ * ```html
8900
+ * <c8y-icon-panel [sections]="sections">
8901
+ * <div class="col-xs-12">
8902
+ * <p>Additional custom content here</p>
8903
+ * </div>
8904
+ * </c8y-icon-panel>
8905
+ * ```
8906
+ */
8907
+ class IconPanelComponent {
8908
+ constructor() {
8909
+ /**
8910
+ * Array of sections to display in the panel
8911
+ */
8912
+ this.sections = [];
8913
+ /**
8914
+ * Accessible label for the icon panel region.
8915
+ */
8916
+ this.ariaLabel = 'Information sections';
8917
+ }
8918
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IconPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8919
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: IconPanelComponent, isStandalone: true, selector: "c8y-icon-panel", inputs: { sections: "sections", ariaLabel: "ariaLabel" }, ngImport: i0, template: "<div\n class=\"d-flex row tight-grid flex-wrap a-i-stretch\"\n [attr.aria-label]=\"ariaLabel | translate\"\n role=\"region\"\n data-cy=\"c8y-icon-panel\"\n>\n @for (section of sections; track section.id) {\n @if (section.visible) {\n <div\n class=\"d-flex m-b-8\"\n [attr.aria-label]=\"\n (section.label | translate) + ': ' + (section.content | translate | stripHtml)\n \"\n role=\"definition\"\n [ngClass]=\"section.colClass || 'col-xs-12 col-md-6'\"\n [attr.data-cy]=\"section.dataCy\"\n >\n <div [ngClass]=\"section.containerClass || 'border-all fit-w d-flex'\">\n <div class=\"p-8\">\n <i\n [class]=\"'icon-24 m-t-4 c8y-icon ' + (section.iconClass || '')\"\n [c8yIcon]=\"section.icon\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8 flex-grow\">\n <p class=\"text-label-small m-b-4\">{{ section.label | translate }}</p>\n <div\n class=\"small fit-w\"\n [innerHTML]=\"section.content | translate\"\n ></div>\n </div>\n </div>\n </div>\n }\n }\n\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: StripHtmlPipe, name: "stripHtml" }] }); }
8920
+ }
8921
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: IconPanelComponent, decorators: [{
8922
+ type: Component,
8923
+ args: [{ selector: 'c8y-icon-panel', standalone: true, imports: [NgClass, C8yTranslatePipe, IconDirective, StripHtmlPipe], template: "<div\n class=\"d-flex row tight-grid flex-wrap a-i-stretch\"\n [attr.aria-label]=\"ariaLabel | translate\"\n role=\"region\"\n data-cy=\"c8y-icon-panel\"\n>\n @for (section of sections; track section.id) {\n @if (section.visible) {\n <div\n class=\"d-flex m-b-8\"\n [attr.aria-label]=\"\n (section.label | translate) + ': ' + (section.content | translate | stripHtml)\n \"\n role=\"definition\"\n [ngClass]=\"section.colClass || 'col-xs-12 col-md-6'\"\n [attr.data-cy]=\"section.dataCy\"\n >\n <div [ngClass]=\"section.containerClass || 'border-all fit-w d-flex'\">\n <div class=\"p-8\">\n <i\n [class]=\"'icon-24 m-t-4 c8y-icon ' + (section.iconClass || '')\"\n [c8yIcon]=\"section.icon\"\n aria-hidden=\"true\"\n ></i>\n </div>\n <div class=\"p-t-8 p-b-8 p-r-8 flex-grow\">\n <p class=\"text-label-small m-b-4\">{{ section.label | translate }}</p>\n <div\n class=\"small fit-w\"\n [innerHTML]=\"section.content | translate\"\n ></div>\n </div>\n </div>\n </div>\n }\n }\n\n <ng-content></ng-content>\n</div>\n" }]
8924
+ }], propDecorators: { sections: [{
8925
+ type: Input
8926
+ }], ariaLabel: [{
8927
+ type: Input
8928
+ }] } });
8929
+
8808
8930
  class GeoService {
8809
8931
  constructor() {
8810
8932
  this.C8Y_POSITION_FRAGMENT = 'c8y_Position';
@@ -11731,6 +11853,55 @@ class DynamicBulkIIdentifiedResolver extends DynamicBulkDetailsResolver {
11731
11853
  }
11732
11854
  }
11733
11855
 
11856
+ class MOChunkLoaderService {
11857
+ constructor(inventory) {
11858
+ this.inventory = inventory;
11859
+ }
11860
+ async processInChunks(ids, chunkSize, loadChunkFn) {
11861
+ if (!ids.length) {
11862
+ return { results: [], errors: [] };
11863
+ }
11864
+ const promiseArray = [];
11865
+ const idsCopy = [...ids];
11866
+ while (idsCopy.length) {
11867
+ const batch = idsCopy.splice(0, chunkSize);
11868
+ promiseArray.push(loadChunkFn(batch));
11869
+ }
11870
+ const chunkResults = await Promise.all(promiseArray);
11871
+ const results = chunkResults.flatMap(r => r.managedObjects);
11872
+ const errors = chunkResults.flatMap(r => r.errors);
11873
+ return { results, errors };
11874
+ }
11875
+ async loadAChunkOfManagedObjectsBase(uniqIds, inventory, pageSize, getStatusDetails, queryFilter) {
11876
+ const { data: managedObjects } = await inventory.list(Object.assign({}, queryFilter || {}, {
11877
+ ids: uniqIds.join(),
11878
+ pageSize
11879
+ }));
11880
+ const notFoundMOs = uniqIds.filter(id => !managedObjects.find(tmp => tmp.id === id));
11881
+ if (notFoundMOs.length) {
11882
+ const promArray = notFoundMOs.map(id => getStatusDetails(id));
11883
+ const res = await Promise.all(promArray);
11884
+ return { managedObjects, errors: res };
11885
+ }
11886
+ return { managedObjects, errors: [] };
11887
+ }
11888
+ async getStatusDetails(moId) {
11889
+ try {
11890
+ const res = await this.inventory.detail(moId);
11891
+ return { id: moId, ...pick(res.res, ['status', 'statusText']) };
11892
+ }
11893
+ catch (e) {
11894
+ return { id: moId, ...pick(e.res, ['status', 'statusText']) };
11895
+ }
11896
+ }
11897
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, deps: [{ token: i1.InventoryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
11898
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, providedIn: 'root' }); }
11899
+ }
11900
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, decorators: [{
11901
+ type: Injectable,
11902
+ args: [{ providedIn: 'root' }]
11903
+ }], ctorParameters: () => [{ type: i1.InventoryService }] });
11904
+
11734
11905
  /**
11735
11906
  * A DynamicDetailsResolver responsible to resolve managedObjects for dynamic components.
11736
11907
  * This service implements bulk resolving. This reduces the number of requests made to
@@ -11875,55 +12046,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
11875
12046
  args: [{ providedIn: 'root' }]
11876
12047
  }] });
11877
12048
 
11878
- class MOChunkLoaderService {
11879
- constructor(inventory) {
11880
- this.inventory = inventory;
11881
- }
11882
- async processInChunks(ids, chunkSize, loadChunkFn) {
11883
- if (!ids.length) {
11884
- return { results: [], errors: [] };
11885
- }
11886
- const promiseArray = [];
11887
- const idsCopy = [...ids];
11888
- while (idsCopy.length) {
11889
- const batch = idsCopy.splice(0, chunkSize);
11890
- promiseArray.push(loadChunkFn(batch));
11891
- }
11892
- const chunkResults = await Promise.all(promiseArray);
11893
- const results = chunkResults.flatMap(r => r.managedObjects);
11894
- const errors = chunkResults.flatMap(r => r.errors);
11895
- return { results, errors };
11896
- }
11897
- async loadAChunkOfManagedObjectsBase(uniqIds, inventory, pageSize, getStatusDetails, queryFilter) {
11898
- const { data: managedObjects } = await inventory.list(Object.assign({}, queryFilter || {}, {
11899
- ids: uniqIds.join(),
11900
- pageSize
11901
- }));
11902
- const notFoundMOs = uniqIds.filter(id => !managedObjects.find(tmp => tmp.id === id));
11903
- if (notFoundMOs.length) {
11904
- const promArray = notFoundMOs.map(id => getStatusDetails(id));
11905
- const res = await Promise.all(promArray);
11906
- return { managedObjects, errors: res };
11907
- }
11908
- return { managedObjects, errors: [] };
11909
- }
11910
- async getStatusDetails(moId) {
11911
- try {
11912
- const res = await this.inventory.detail(moId);
11913
- return { id: moId, ...pick(res.res, ['status', 'statusText']) };
11914
- }
11915
- catch (e) {
11916
- return { id: moId, ...pick(e.res, ['status', 'statusText']) };
11917
- }
11918
- }
11919
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, deps: [{ token: i1.InventoryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
11920
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, providedIn: 'root' }); }
11921
- }
11922
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: MOChunkLoaderService, decorators: [{
11923
- type: Injectable,
11924
- args: [{ providedIn: 'root' }]
11925
- }], ctorParameters: () => [{ type: i1.InventoryService }] });
11926
-
11927
12049
  class AppSwitcherService {
11928
12050
  constructor(ui) {
11929
12051
  this.ui = ui;
@@ -29186,7 +29308,7 @@ class DashboardChildChange {
29186
29308
  this.child = childToChange;
29187
29309
  }
29188
29310
  get resize$() {
29189
- return this.child.dragSource.moved.pipe(map(move => this.getPixelSize(move)), tap(resizeDimension => this.setPixelSize(resizeDimension)), map(resizeDimension => this.getDimensionSize(resizeDimension)), distinctUntilChanged((prev, next) => prev.width === next.width && prev.height === next.height), map(dimension => this.setDimension(dimension)), tap(() => console.log('Resize dimension:', this.child)), this.arrangePipe());
29311
+ return this.child.dragSource.moved.pipe(map(move => this.getPixelSize(move)), tap(resizeDimension => this.setPixelSize(resizeDimension)), map(resizeDimension => this.getDimensionSize(resizeDimension)), distinctUntilChanged((prev, next) => prev.width === next.width && prev.height === next.height), map(dimension => this.setDimension(dimension)), this.arrangePipe());
29190
29312
  }
29191
29313
  get drag$() {
29192
29314
  return this.child.dragSource.moved.pipe(map(move => this.getDimensionPosition(move)), filter(dimension => dimension.x >= 0 &&
@@ -37594,9 +37716,22 @@ class RealtimeMessage {
37594
37716
  }
37595
37717
 
37596
37718
  /**
37597
- * A resizable grid component with two columns (A and B).
37598
- * Allows the user to resize columns by dragging the divider.
37599
- * Supports collapse/expand logic and persistent width via localStorage.
37719
+ * Resizable Grid Component
37720
+ *
37721
+ * Provides a flexible layout with two adjustable columns separated by a draggable divider.
37722
+ *
37723
+ * ## Basic Usage
37724
+ *
37725
+ * ```html
37726
+ * <c8y-resizable-grid
37727
+ * [leftColumnWidth]="'50%'"
37728
+ * [collapseThreshold]="320"
37729
+ * [collapsible]="true"
37730
+ * [trackId]="'my-layout'">
37731
+ * <div #colA>Left column content</div>
37732
+ * <div #colB>Right column content</div>
37733
+ * </c8y-resizable-grid>
37734
+ * ```
37600
37735
  */
37601
37736
  class ResizableGridComponent {
37602
37737
  /**
@@ -37627,6 +37762,10 @@ class ResizableGridComponent {
37627
37762
  * Minimum width (in pixels) before a column is considered collapsed.
37628
37763
  */
37629
37764
  this.collapseThreshold = 320;
37765
+ /**
37766
+ * If true, columns can collapse below the threshold. If false, columns stop at the threshold.
37767
+ */
37768
+ this.collapsible = true;
37630
37769
  /**
37631
37770
  * True if the user is currently resizing the grid.
37632
37771
  */
@@ -37813,10 +37952,12 @@ class ResizableGridComponent {
37813
37952
  if (!this.colA || !this.colB) {
37814
37953
  return;
37815
37954
  }
37816
- let newWidthPx = Math.max(0, targetWidthPx);
37817
37955
  const totalWidth = this.colA.nativeElement.parentElement?.offsetWidth || window.innerWidth;
37818
- const minColBWidthPx = 0; // Allow colB to go down to 0 for collapsing
37819
- newWidthPx = Math.min(newWidthPx, totalWidth - minColBWidthPx);
37956
+ // If not collapsible, enforce the threshold as the minimum
37957
+ const minWidthPx = this.collapsible ? 0 : this.collapseThreshold;
37958
+ const maxWidthPx = this.collapsible ? totalWidth : totalWidth - this.collapseThreshold;
37959
+ let newWidthPx = Math.max(minWidthPx, targetWidthPx);
37960
+ newWidthPx = Math.min(newWidthPx, maxWidthPx);
37820
37961
  const newWidthString = `${newWidthPx}px`;
37821
37962
  this._colAWidth = newWidthString;
37822
37963
  // Update lastKnownNonCollapsedWidth during drag, regardless of trackId
@@ -37844,25 +37985,38 @@ class ResizableGridComponent {
37844
37985
  const colANative = this.colA.nativeElement;
37845
37986
  const colBNative = this.colB.nativeElement;
37846
37987
  this.removeCollapseClasses();
37847
- if (colAWidth < this.collapseThreshold) {
37848
- this.renderer.addClass(colANative, 'collapsed');
37849
- this.renderer.addClass(colBNative, 'expanded');
37850
- this._colAWidth = '0px';
37851
- }
37852
- else if (colBWidth < this.collapseThreshold) {
37853
- this.renderer.addClass(colBNative, 'collapsed');
37854
- this.renderer.addClass(colANative, 'expanded');
37855
- this._colAWidth = '100%';
37988
+ // Only apply collapse logic if collapsible is true
37989
+ if (this.collapsible) {
37990
+ if (colAWidth < this.collapseThreshold) {
37991
+ this.renderer.addClass(colANative, 'collapsed');
37992
+ this.renderer.addClass(colBNative, 'expanded');
37993
+ this._colAWidth = '0px';
37994
+ }
37995
+ else if (colBWidth < this.collapseThreshold) {
37996
+ this.renderer.addClass(colBNative, 'collapsed');
37997
+ this.renderer.addClass(colANative, 'expanded');
37998
+ this._colAWidth = '100%';
37999
+ }
38000
+ else {
38001
+ // If neither is collapsed, restore the last known non-collapsed width.
38002
+ // This will be the actual width from the drag, or the localStorage value.
38003
+ this._colAWidth = this.lastKnownNonCollapsedWidth || this.leftColumnWidth;
38004
+ if (this.trackId) {
38005
+ // Ensure localStorage is up-to-date if no collapse occurred.
38006
+ const saved = localStorage.getItem(this.trackId);
38007
+ if (saved !== this._colAWidth) {
38008
+ // Only write if different
38009
+ localStorage.setItem(this.trackId, this._colAWidth);
38010
+ }
38011
+ }
38012
+ }
37856
38013
  }
37857
38014
  else {
37858
- // If neither is collapsed, restore the last known non-collapsed width.
37859
- // This will be the actual width from the drag, or the localStorage value.
38015
+ // When not collapsible, just maintain the current width without collapse
37860
38016
  this._colAWidth = this.lastKnownNonCollapsedWidth || this.leftColumnWidth;
37861
38017
  if (this.trackId) {
37862
- // Ensure localStorage is up-to-date if no collapse occurred.
37863
38018
  const saved = localStorage.getItem(this.trackId);
37864
38019
  if (saved !== this._colAWidth) {
37865
- // Only write if different
37866
38020
  localStorage.setItem(this.trackId, this._colAWidth);
37867
38021
  }
37868
38022
  }
@@ -37883,7 +38037,7 @@ class ResizableGridComponent {
37883
38037
  this.renderer.removeClass(colBNative, 'expanded');
37884
38038
  }
37885
38039
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ResizableGridComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
37886
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ResizableGridComponent, isStandalone: true, selector: "c8y-resizable-grid", inputs: { leftColumnWidth: "leftColumnWidth", trackId: "trackId", collapseThreshold: "collapseThreshold" }, host: { listeners: { "window:mousemove": "onMouseMove($event)", "window:mouseup": "onMouseUp()" }, properties: { "class.is-resizing": "this.isResizing", "style.--col-a-width": "this._colAWidth" } }, viewQueries: [{ propertyName: "colA", first: true, predicate: ["colA"], descendants: true }, { propertyName: "colB", first: true, predicate: ["colB"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"resizable-grid-container\" [class.is-resizing]=\"isResizing\">\n <div #colA class=\"col-a\" [id]=\"colAId\">\n <!-- Content for the left column goes here -->\n <ng-content select=\"[left-pane]\"></ng-content>\n </div>\n <div\n class=\"resizer\"\n (mousedown)=\"onMouseDown($event)\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n [attr.aria-controls]=\"colAId + ' ' + colBId\"\n [attr.aria-label]=\"'Resize columns' | translate\"\n [attr.aria-valuenow]=\"colAWidthPercent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <i class=\"dlt-c8y-icon-arrow-circle-divide-horizontal\"></i>\n </div>\n <div #colB class=\"col-b\" [id]=\"colBId\">\n <!-- Content for the right column goes here -->\n <ng-content select=\"[right-pane]\"></ng-content>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
38040
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: ResizableGridComponent, isStandalone: true, selector: "c8y-resizable-grid", inputs: { leftColumnWidth: "leftColumnWidth", trackId: "trackId", collapseThreshold: "collapseThreshold", collapsible: "collapsible" }, host: { listeners: { "window:mousemove": "onMouseMove($event)", "window:mouseup": "onMouseUp()" }, properties: { "class.is-resizing": "this.isResizing", "style.--col-a-width": "this._colAWidth" } }, viewQueries: [{ propertyName: "colA", first: true, predicate: ["colA"], descendants: true }, { propertyName: "colB", first: true, predicate: ["colB"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"resizable-grid-container\" [class.is-resizing]=\"isResizing\">\n <div #colA class=\"col-a\" [id]=\"colAId\">\n <!-- Content for the left column goes here -->\n <ng-content select=\"[left-pane]\"></ng-content>\n </div>\n <div\n class=\"resizer\"\n (mousedown)=\"onMouseDown($event)\"\n (keydown)=\"onKeyDown($event)\"\n tabindex=\"0\"\n role=\"separator\"\n aria-orientation=\"vertical\"\n [attr.aria-controls]=\"colAId + ' ' + colBId\"\n [attr.aria-label]=\"'Resize columns' | translate\"\n [attr.aria-valuenow]=\"colAWidthPercent\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n >\n <i class=\"dlt-c8y-icon-arrow-circle-divide-horizontal\"></i>\n </div>\n <div #colB class=\"col-b\" [id]=\"colBId\">\n <!-- Content for the right column goes here -->\n <ng-content select=\"[right-pane]\"></ng-content>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
37887
38041
  }
37888
38042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ResizableGridComponent, decorators: [{
37889
38043
  type: Component,
@@ -37894,6 +38048,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
37894
38048
  type: Input
37895
38049
  }], collapseThreshold: [{
37896
38050
  type: Input
38051
+ }], collapsible: [{
38052
+ type: Input
37897
38053
  }], colA: [{
37898
38054
  type: ViewChild,
37899
38055
  args: ['colA']
@@ -38123,6 +38279,891 @@ function colorValidator(allowedModes) {
38123
38279
  };
38124
38280
  }
38125
38281
 
38282
+ /**
38283
+ * Displays a row of action buttons in the split view details panel.
38284
+ * Renders buttons based on the provided action configurations with support for:
38285
+ * - Icons and translatable labels
38286
+ * - Disabled and visibility states
38287
+ * - Product experience analytics tracking
38288
+ * - Custom tooltips and styling
38289
+ *
38290
+ * @example
38291
+ * ```html
38292
+ * <c8y-sv-details-actions [actions]="detailActions"></c8y-sv-details-actions>
38293
+ * ```
38294
+ *
38295
+ * @example
38296
+ * ```typescript
38297
+ * detailActions: SplitViewAction[] = [
38298
+ * {
38299
+ * id: 'edit',
38300
+ * label: 'Edit',
38301
+ * icon: 'pencil',
38302
+ * class: 'btn btn-primary',
38303
+ * action: () => this.editItem(),
38304
+ * title: 'Edit this item'
38305
+ * },
38306
+ * {
38307
+ * id: 'delete',
38308
+ * label: 'Delete',
38309
+ * icon: 'trash',
38310
+ * class: 'btn btn-danger',
38311
+ * action: () => this.deleteItem(),
38312
+ * productExperience: {
38313
+ * actionName: 'delete_item',
38314
+ * actionData: { itemType: 'device' }
38315
+ * }
38316
+ * }
38317
+ * ];
38318
+ * ```
38319
+ */
38320
+ class SplitViewDetailsActionsComponent {
38321
+ constructor() {
38322
+ /**
38323
+ * Array of action configurations to display as buttons.
38324
+ * Buttons are rendered in the order provided.
38325
+ */
38326
+ this.actions = [];
38327
+ }
38328
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewDetailsActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38329
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SplitViewDetailsActionsComponent, isStandalone: true, selector: "c8y-sv-details-actions", inputs: { actions: "actions" }, ngImport: i0, template: "<div\n class=\"d-flex gap-8 a-i-center\"\n [attr.aria-label]=\"'Actions' | translate\"\n role=\"group\"\n data-cy=\"c8y-sv-details-actions\"\n>\n @for (action of actions; track action.id) {\n @if (action.visible !== false) {\n <button\n [title]=\"action.title ? (action.title | translate) : null\"\n [attr.aria-label]=\"action.title ? (action.title | translate) : (action.label | translate)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : 'false'\"\n type=\"button\"\n [ngClass]=\"action.class || ''\"\n [disabled]=\"action.disabled || false\"\n [attr.data-cy]=\"action.dataCy\"\n (click)=\"action.action()\"\n c8yProductExperience\n [actionName]=\"action.productExperience?.actionName\"\n [actionData]=\"action.productExperience?.actionData\"\n >\n <i\n [c8yIcon]=\"action.icon\"\n aria-hidden=\"true\"\n [ngClass]=\"action.iconClass || ''\"\n ></i>\n {{ action.label | translate }}\n </button>\n }\n }\n\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
38330
+ }
38331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewDetailsActionsComponent, decorators: [{
38332
+ type: Component,
38333
+ args: [{ selector: 'c8y-sv-details-actions', standalone: true, imports: [NgClass, C8yTranslatePipe, IconDirective, ProductExperienceDirective], template: "<div\n class=\"d-flex gap-8 a-i-center\"\n [attr.aria-label]=\"'Actions' | translate\"\n role=\"group\"\n data-cy=\"c8y-sv-details-actions\"\n>\n @for (action of actions; track action.id) {\n @if (action.visible !== false) {\n <button\n [title]=\"action.title ? (action.title | translate) : null\"\n [attr.aria-label]=\"action.title ? (action.title | translate) : (action.label | translate)\"\n [attr.aria-disabled]=\"action.disabled ? 'true' : 'false'\"\n type=\"button\"\n [ngClass]=\"action.class || ''\"\n [disabled]=\"action.disabled || false\"\n [attr.data-cy]=\"action.dataCy\"\n (click)=\"action.action()\"\n c8yProductExperience\n [actionName]=\"action.productExperience?.actionName\"\n [actionData]=\"action.productExperience?.actionData\"\n >\n <i\n [c8yIcon]=\"action.icon\"\n aria-hidden=\"true\"\n [ngClass]=\"action.iconClass || ''\"\n ></i>\n {{ action.label | translate }}\n </button>\n }\n }\n\n <ng-content></ng-content>\n</div>\n" }]
38334
+ }], propDecorators: { actions: [{
38335
+ type: Input
38336
+ }] } });
38337
+
38338
+ /**
38339
+ * Extra header component for split view details.
38340
+ * Provides a flexible content projection area below the main header.
38341
+ *
38342
+ * Use this component to add custom content like metadata, status information,
38343
+ * or any other details you want to display at the top of the details panel.
38344
+ *
38345
+ * @example
38346
+ * ```html
38347
+ * <c8y-sv-details>
38348
+ * <c8y-sv-extra-header>
38349
+ * <div class="row p-16">
38350
+ * <div class="col-sm-6">
38351
+ * <label>Device ID:</label>
38352
+ * <span>{{ device.id }}</span>
38353
+ * </div>
38354
+ * <div class="col-sm-6">
38355
+ * <label>Status:</label>
38356
+ * <span>{{ device.status }}</span>
38357
+ * </div>
38358
+ * </div>
38359
+ * </c8y-sv-extra-header>
38360
+ * </c8y-sv-details>
38361
+ * ```
38362
+ */
38363
+ class SplitViewExtraHeaderComponent {
38364
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewExtraHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38365
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SplitViewExtraHeaderComponent, isStandalone: true, selector: "c8y-sv-extra-header", host: { classAttribute: "d-contents" }, ngImport: i0, template: '<ng-content></ng-content>', isInline: true }); }
38366
+ }
38367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewExtraHeaderComponent, decorators: [{
38368
+ type: Component,
38369
+ args: [{
38370
+ selector: 'c8y-sv-extra-header',
38371
+ template: '<ng-content></ng-content>',
38372
+ host: { class: 'd-contents' },
38373
+ standalone: true
38374
+ }]
38375
+ }] });
38376
+
38377
+ class SplitViewFooterComponent {
38378
+ constructor() {
38379
+ this.cssClass = '';
38380
+ }
38381
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38382
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SplitViewFooterComponent, isStandalone: true, selector: "c8y-sv-footer", inputs: { cssClass: "cssClass" }, host: { classAttribute: "d-contents" }, ngImport: i0, template: "<div\n class=\"card-footer separator-top fit-w sticky-bottom m-t-auto bg-inherit\"\n [ngClass]=\"cssClass\"\n data-cy=\"c8y-sv-footer\"\n>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
38383
+ }
38384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewFooterComponent, decorators: [{
38385
+ type: Component,
38386
+ args: [{ selector: 'c8y-sv-footer', host: { class: 'd-contents' }, standalone: true, imports: [NgClass], template: "<div\n class=\"card-footer separator-top fit-w sticky-bottom m-t-auto bg-inherit\"\n [ngClass]=\"cssClass\"\n data-cy=\"c8y-sv-footer\"\n>\n <ng-content></ng-content>\n</div>\n" }]
38387
+ }], propDecorators: { cssClass: [{
38388
+ type: Input
38389
+ }] } });
38390
+
38391
+ /**
38392
+ * Service to manage selection state in split view components.
38393
+ * Provides methods to select/deselect items and track selection state.
38394
+ */
38395
+ class SplitViewSelectionService {
38396
+ constructor() {
38397
+ this._selectedItem$ = new BehaviorSubject(null);
38398
+ }
38399
+ ngOnDestroy() {
38400
+ this._selectedItem$.complete();
38401
+ }
38402
+ /**
38403
+ * Observable of the currently selected item
38404
+ */
38405
+ get selectedItem$() {
38406
+ return this._selectedItem$.asObservable();
38407
+ }
38408
+ /**
38409
+ * Get the current selected item value
38410
+ */
38411
+ get selectedItem() {
38412
+ return this._selectedItem$.value;
38413
+ }
38414
+ /**
38415
+ * Check if an item is currently selected
38416
+ */
38417
+ get hasSelection() {
38418
+ return this._selectedItem$.value !== null;
38419
+ }
38420
+ /**
38421
+ * Select an item
38422
+ */
38423
+ select(item) {
38424
+ this._selectedItem$.next(item);
38425
+ }
38426
+ /**
38427
+ * Clear the current selection
38428
+ */
38429
+ clearSelection() {
38430
+ this._selectedItem$.next(null);
38431
+ }
38432
+ /**
38433
+ * Check if a specific item is selected
38434
+ */
38435
+ isSelected(item) {
38436
+ return this._selectedItem$.value === item;
38437
+ }
38438
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38439
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewSelectionService }); }
38440
+ }
38441
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewSelectionService, decorators: [{
38442
+ type: Injectable
38443
+ }] });
38444
+
38445
+ /**
38446
+ * Split View Details Component
38447
+ *
38448
+ * Displays the details panel of a split-view layout.
38449
+ *
38450
+ * ## Basic Usage
38451
+ *
38452
+ * ```html
38453
+ * <c8y-sv-details
38454
+ * emptyStateIcon="c8y-devices"
38455
+ * emptyStateTitle="No device selected"
38456
+ * emptyStateSubtitle="Select a device to view details">
38457
+ *
38458
+ * @if (selectedItem) {
38459
+ * <c8y-sv-extra-header>
38460
+ * <c8y-icon-panel [sections]="sections"></c8y-icon-panel>
38461
+ * </c8y-sv-extra-header>
38462
+ * }
38463
+ *
38464
+ * @if (selectedItem) {
38465
+ * <h3>{{ selectedItem.name }}</h3>
38466
+ * <p>{{ selectedItem.description }}</p>
38467
+ * }
38468
+ * </c8y-sv-details>
38469
+ * ```
38470
+ *
38471
+ * ## Router-Outlet Integration
38472
+ *
38473
+ * ```html
38474
+ * <c8y-sv-details (backClick)="handleBackClick()">
38475
+ * <router-outlet></router-outlet>
38476
+ * </c8y-sv-details>
38477
+ * ```
38478
+ *
38479
+ * ```typescript
38480
+ * async handleBackClick(): Promise<void> {
38481
+ * await this.alarmsViewService.closeDetailsView(this.activatedRoute);
38482
+ * }
38483
+ * ```
38484
+ */
38485
+ class SplitViewDetailsComponent {
38486
+ constructor(selectionService, location, cdr) {
38487
+ this.selectionService = selectionService;
38488
+ this.location = location;
38489
+ this.cdr = cdr;
38490
+ this.destroyRef = inject(DestroyRef);
38491
+ this._routerOutletActivated = false;
38492
+ /**
38493
+ * Aria label for the details panel region.
38494
+ */
38495
+ this.ariaLabel = gettext$1('Details panel');
38496
+ /**
38497
+ * Custom CSS classes
38498
+ */
38499
+ this.cssClass = '';
38500
+ /**
38501
+ * Empty state icon when nothing is selected
38502
+ */
38503
+ this.emptyStateIcon = 'c8y-alert-idle';
38504
+ /**
38505
+ * Empty state title when nothing is selected
38506
+ */
38507
+ this.emptyStateTitle = gettext$1('No item selected');
38508
+ /**
38509
+ * Empty state subtitle when nothing is selected
38510
+ */
38511
+ this.emptyStateSubtitle = gettext$1('Select an item from the list to view details');
38512
+ /**
38513
+ * Emits when the back button is clicked.
38514
+ * Allows parent components to handle custom navigation logic.
38515
+ * If not handled, default behavior (location.back or clearSelection) is used.
38516
+ */
38517
+ this.backClick = new EventEmitter();
38518
+ }
38519
+ ngAfterViewInit() {
38520
+ // Listen to router outlet activation/deactivation events directly
38521
+ if (this.routerOutlet) {
38522
+ // Set initial state and mark for check
38523
+ this._routerOutletActivated = !!this.routerOutlet.isActivated;
38524
+ this.cdr?.markForCheck();
38525
+ // Subscribe to activation events
38526
+ this.routerOutlet.activateEvents.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
38527
+ this._routerOutletActivated = true;
38528
+ this.cdr?.markForCheck();
38529
+ });
38530
+ // Subscribe to deactivation events
38531
+ this.routerOutlet.deactivateEvents.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
38532
+ this._routerOutletActivated = false;
38533
+ this.cdr?.markForCheck();
38534
+ });
38535
+ }
38536
+ }
38537
+ ngOnDestroy() {
38538
+ this.backClick.complete();
38539
+ }
38540
+ get hasExtraHeader() {
38541
+ return !!this.extraHeaderComponent;
38542
+ }
38543
+ get hasActions() {
38544
+ return !!this.actionsComponent;
38545
+ }
38546
+ get hasFooter() {
38547
+ return !!this.footerComponent;
38548
+ }
38549
+ /**
38550
+ * Check if an item is selected or if router-outlet is activated
38551
+ */
38552
+ get hasSelection() {
38553
+ // Check selection service first
38554
+ if (this.selectionService?.hasSelection) {
38555
+ return true;
38556
+ }
38557
+ // Check router outlet activation state (updated via outlet events)
38558
+ return this._routerOutletActivated;
38559
+ }
38560
+ /**
38561
+ * Clear the current selection (back button handler).
38562
+ * Emits backClick event for parent to handle, or uses default behavior:
38563
+ * - Router-outlet: navigates back using browser history
38564
+ * - Selection service: clears the selection
38565
+ */
38566
+ clearSelection() {
38567
+ // Emit event for parent to handle
38568
+ if (this.backClick.observed) {
38569
+ this.backClick.emit();
38570
+ }
38571
+ // Default behavior: If using router-outlet, go back in history
38572
+ else if (this.routerOutlet?.isActivated && this.location) {
38573
+ this.location.back();
38574
+ }
38575
+ // Otherwise clear selection service
38576
+ else {
38577
+ this.selectionService?.clearSelection();
38578
+ }
38579
+ }
38580
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewDetailsComponent, deps: [{ token: SplitViewSelectionService, optional: true }, { token: i1$a.Location, optional: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
38581
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SplitViewDetailsComponent, isStandalone: true, selector: "c8y-sv-details", inputs: { title: "title", ariaLabel: "ariaLabel", cssClass: "cssClass", emptyStateIcon: "emptyStateIcon", emptyStateTitle: "emptyStateTitle", emptyStateSubtitle: "emptyStateSubtitle" }, outputs: { backClick: "backClick" }, host: { classAttribute: "d-contents" }, queries: [{ propertyName: "extraHeaderComponent", first: true, predicate: SplitViewExtraHeaderComponent, descendants: true }, { propertyName: "actionsComponent", first: true, predicate: SplitViewDetailsActionsComponent, descendants: true }, { propertyName: "footerComponent", first: true, predicate: SplitViewFooterComponent, descendants: true }, { propertyName: "routerOutlet", first: true, predicate: RouterOutlet, descendants: true }], ngImport: i0, template: "<div\n class=\"inner-scroll fit-h d-col fit-w split-view__detail\"\n [class.split-view__detail--selected]=\"hasSelection\"\n [attr.aria-label]=\"ariaLabel | translate\"\n role=\"region\"\n [ngClass]=\"cssClass\"\n data-cy=\"c8y-sv-details\"\n>\n <!-- Back button for mobile/tablet -->\n @if (hasSelection) {\n <div class=\"card-header separator sticky-top visible-sm visible-xs\">\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Back' | translate\"\n [attr.aria-label]=\"'Back' | translate\"\n type=\"button\"\n (click)=\"clearSelection()\"\n >\n <i c8yIcon=\"chevron-left\"></i>\n <span>{{ 'Back' | translate }}</span>\n </button>\n </div>\n }\n <!-- Content when item is selected -->\n @if (title || hasExtraHeader) {\n <div\n class=\"p-l-24 p-r-24 card-header flex-no-shrink sticky-top bg-component separator\"\n [ngClass]=\"{ 'flex-wrap': hasExtraHeader, 'gap-8': hasExtraHeader && title }\"\n >\n <h4 class=\"card-title\">{{ title | translate }}</h4>\n <ng-content select=\"c8y-sv-header-actions\"></ng-content>\n @if (hasExtraHeader) {\n <div class=\"details-info fit-w\">\n <ng-content select=\"c8y-sv-extra-header\"></ng-content>\n </div>\n }\n </div>\n }\n <!-- Empty state when nothing is selected -->\n @if (!hasSelection) {\n <div class=\"d-flex a-i-center j-c-center flex-grow p-24\">\n <c8y-ui-empty-state\n [icon]=\"emptyStateIcon\"\n [title]=\"emptyStateTitle\"\n [subtitle]=\"emptyStateSubtitle\"\n ></c8y-ui-empty-state>\n </div>\n }\n <!-- Content when item is selected -->\n @if (hasSelection) {\n <div\n class=\"p-24\"\n [ngClass]=\"{ 'p-t-0': !title && !hasExtraHeader }\"\n >\n <div class=\"details-content\">\n <ng-content\n select=\":not(c8y-sv-extra-header):not(c8y-sv-details-actions):not(c8y-sv-footer):not(c8y-sv-header-actions)\"\n ></ng-content>\n </div>\n\n @if (hasActions) {\n <div class=\"details-actions\">\n <ng-content select=\"c8y-sv-details-actions\"></ng-content>\n </div>\n }\n </div>\n @if (hasFooter) {\n <ng-content select=\"c8y-sv-footer\"></ng-content>\n }\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
38582
+ }
38583
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewDetailsComponent, decorators: [{
38584
+ type: Component,
38585
+ args: [{ selector: 'c8y-sv-details', host: { class: 'd-contents' }, standalone: true, imports: [NgClass, C8yTranslatePipe, EmptyStateComponent, IconDirective], template: "<div\n class=\"inner-scroll fit-h d-col fit-w split-view__detail\"\n [class.split-view__detail--selected]=\"hasSelection\"\n [attr.aria-label]=\"ariaLabel | translate\"\n role=\"region\"\n [ngClass]=\"cssClass\"\n data-cy=\"c8y-sv-details\"\n>\n <!-- Back button for mobile/tablet -->\n @if (hasSelection) {\n <div class=\"card-header separator sticky-top visible-sm visible-xs\">\n <button\n class=\"btn btn-clean text-primary\"\n [title]=\"'Back' | translate\"\n [attr.aria-label]=\"'Back' | translate\"\n type=\"button\"\n (click)=\"clearSelection()\"\n >\n <i c8yIcon=\"chevron-left\"></i>\n <span>{{ 'Back' | translate }}</span>\n </button>\n </div>\n }\n <!-- Content when item is selected -->\n @if (title || hasExtraHeader) {\n <div\n class=\"p-l-24 p-r-24 card-header flex-no-shrink sticky-top bg-component separator\"\n [ngClass]=\"{ 'flex-wrap': hasExtraHeader, 'gap-8': hasExtraHeader && title }\"\n >\n <h4 class=\"card-title\">{{ title | translate }}</h4>\n <ng-content select=\"c8y-sv-header-actions\"></ng-content>\n @if (hasExtraHeader) {\n <div class=\"details-info fit-w\">\n <ng-content select=\"c8y-sv-extra-header\"></ng-content>\n </div>\n }\n </div>\n }\n <!-- Empty state when nothing is selected -->\n @if (!hasSelection) {\n <div class=\"d-flex a-i-center j-c-center flex-grow p-24\">\n <c8y-ui-empty-state\n [icon]=\"emptyStateIcon\"\n [title]=\"emptyStateTitle\"\n [subtitle]=\"emptyStateSubtitle\"\n ></c8y-ui-empty-state>\n </div>\n }\n <!-- Content when item is selected -->\n @if (hasSelection) {\n <div\n class=\"p-24\"\n [ngClass]=\"{ 'p-t-0': !title && !hasExtraHeader }\"\n >\n <div class=\"details-content\">\n <ng-content\n select=\":not(c8y-sv-extra-header):not(c8y-sv-details-actions):not(c8y-sv-footer):not(c8y-sv-header-actions)\"\n ></ng-content>\n </div>\n\n @if (hasActions) {\n <div class=\"details-actions\">\n <ng-content select=\"c8y-sv-details-actions\"></ng-content>\n </div>\n }\n </div>\n @if (hasFooter) {\n <ng-content select=\"c8y-sv-footer\"></ng-content>\n }\n }\n</div>\n" }]
38586
+ }], ctorParameters: () => [{ type: SplitViewSelectionService, decorators: [{
38587
+ type: Optional
38588
+ }] }, { type: i1$a.Location, decorators: [{
38589
+ type: Optional
38590
+ }] }, { type: i0.ChangeDetectorRef }], propDecorators: { title: [{
38591
+ type: Input
38592
+ }], ariaLabel: [{
38593
+ type: Input
38594
+ }], cssClass: [{
38595
+ type: Input
38596
+ }], emptyStateIcon: [{
38597
+ type: Input
38598
+ }], emptyStateTitle: [{
38599
+ type: Input
38600
+ }], emptyStateSubtitle: [{
38601
+ type: Input
38602
+ }], backClick: [{
38603
+ type: Output
38604
+ }], extraHeaderComponent: [{
38605
+ type: ContentChild,
38606
+ args: [SplitViewExtraHeaderComponent]
38607
+ }], actionsComponent: [{
38608
+ type: ContentChild,
38609
+ args: [SplitViewDetailsActionsComponent]
38610
+ }], footerComponent: [{
38611
+ type: ContentChild,
38612
+ args: [SplitViewFooterComponent]
38613
+ }], routerOutlet: [{
38614
+ type: ContentChild,
38615
+ args: [RouterOutlet]
38616
+ }] } });
38617
+
38618
+ const DEFAULT_RESIZABLE_CONFIG = Object.freeze({
38619
+ collapseThreshold: 320,
38620
+ leftColumnWidth: '50%',
38621
+ trackId: 'c8y-sv-resizable-default',
38622
+ collapsible: true
38623
+ });
38624
+ /**
38625
+ * A responsive split view layout component with automatic selection management and resizable panes.
38626
+ *
38627
+ * #### Basic usage
38628
+ *
38629
+ *
38630
+ * ```typescript
38631
+ * export class MyComponent {
38632
+ * items: Device[] = [];
38633
+ * selectedItem?: Device;
38634
+ *
38635
+ * onSelectionChange(item: Device | null) {
38636
+ * this.selectedItem = item || undefined;
38637
+ * }
38638
+ * }
38639
+ * ```
38640
+ *
38641
+ * ```html
38642
+ * <c8y-sv (selectionChange)="onSelectionChange($event)">
38643
+ * <c8y-sv-list [title]="'Devices'">
38644
+ * <c8y-sv-header-actions>
38645
+ * <button class="btn btn-primary">Add Device</button>
38646
+ * </c8y-sv-header-actions>
38647
+ *
38648
+ * @for (item of items; track item.id) {
38649
+ * <c8y-li [c8ySvListItem]="item">
38650
+ * {{ item.name }}
38651
+ * </c8y-li>
38652
+ * }
38653
+ *
38654
+ * <c8y-sv-footer>
38655
+ * Total: {{ items.length }}
38656
+ * </c8y-sv-footer>
38657
+ * </c8y-sv-list>
38658
+ *
38659
+ * <c8y-sv-details
38660
+ * emptyStateIcon="c8y-devices"
38661
+ * emptyStateTitle="No device selected"
38662
+ * emptyStateSubtitle="Select a device to view details">
38663
+ * @if (selectedItem) {
38664
+ * <c8y-sv-extra-header>
38665
+ * <c8y-icon-panel [sections]="sections"></c8y-icon-panel>
38666
+ * </c8y-sv-extra-header>
38667
+ * }
38668
+ *
38669
+ * @if (selectedItem) {
38670
+ * <h3>{{ selectedItem.name }}</h3>
38671
+ * <p>{{ selectedItem.description }}</p>
38672
+ * }
38673
+ * </c8y-sv-details>
38674
+ * </c8y-sv>
38675
+ * ```
38676
+ *
38677
+ * #### Router-Outlet integration
38678
+ *
38679
+ * For components using Angular router:
38680
+ *
38681
+ * ```html
38682
+ * <c8y-sv>
38683
+ * <c8y-alarms-list>...</c8y-alarms-list>
38684
+ *
38685
+ * <c8y-sv-details (backClick)="handleBackClick()">
38686
+ * <router-outlet></router-outlet>
38687
+ * </c8y-sv-details>
38688
+ * </c8y-sv>
38689
+ * ```
38690
+ *
38691
+ * ```typescript
38692
+ * async handleBackClick(): Promise<void> {
38693
+ * await this.alarmsViewService.closeDetailsView(this.activatedRoute);
38694
+ * }
38695
+ * ```
38696
+ *
38697
+ * #### Resizable configuration
38698
+ *
38699
+ * ```html
38700
+ * <c8y-sv
38701
+ * [isResizable]="true"
38702
+ * [resizableBreakpoint]="991"
38703
+ * [resizableConfig]="{
38704
+ * trackId: 'my-split-view',
38705
+ * leftColumnWidth: '40%',
38706
+ * collapseThreshold: 320,
38707
+ * collapsible: false
38708
+ * }"
38709
+ * [initialSelection]="items[0]"
38710
+ * (selectionChange)="onSelectionChange($event)">
38711
+ * <!-- content -->
38712
+ * </c8y-sv>
38713
+ * ```
38714
+ *
38715
+ * #### List-Only mode
38716
+ *
38717
+ * Omit `<c8y-sv-details>` for a simple list view:
38718
+ * ```html
38719
+ * <c8y-sv>
38720
+ * <c8y-sv-list [title]="'Items'">
38721
+ * @for (item of items; track item.id) {
38722
+ * <c8y-li>{{ item.name }}</c8y-li>
38723
+ * }
38724
+ * </c8y-sv-list>
38725
+ * </c8y-sv>
38726
+ * ```
38727
+ *
38728
+ */
38729
+ class SplitViewComponent {
38730
+ /**
38731
+ * Configuration for resizable grid behavior.
38732
+ *
38733
+ * @property trackId - Unique ID for persisting column widths in localStorage
38734
+ * @property leftColumnWidth - Initial width of left column (default: '50%')
38735
+ * @property collapseThreshold - Width threshold (in px) for collapsing columns (default: 320)
38736
+ * @property collapsible - Whether columns can collapse below threshold (default: true)
38737
+ *
38738
+ * @example
38739
+ * ```html
38740
+ * <c8y-sv [resizableConfig]="{
38741
+ * trackId: 'device-list-view',
38742
+ * leftColumnWidth: '40%',
38743
+ * collapseThreshold: 320,
38744
+ * collapsible: false
38745
+ * }">
38746
+ * ```
38747
+ */
38748
+ set resizableConfig(config) {
38749
+ this._resizableConfig = config ?? {};
38750
+ this.updateMemoizedResizableConfig();
38751
+ }
38752
+ get resizableConfig() {
38753
+ return this._resizableConfig;
38754
+ }
38755
+ constructor(selectionService) {
38756
+ this.selectionService = selectionService;
38757
+ this.destroyRef = inject(DestroyRef);
38758
+ /**
38759
+ * Whether to show a default router outlet in right-view if no right-view slot content provided.
38760
+ * @default true
38761
+ */
38762
+ this.showDefaultRouterOutlet = true;
38763
+ /**
38764
+ * Enable resizable grid functionality with draggable divider.
38765
+ * When `true`, users can resize the split panes by dragging the divider.
38766
+ * Above `resizableBreakpoint`, the resizable grid is active.
38767
+ * Below `resizableBreakpoint`, falls back to CSS-based responsive layout.
38768
+ * @default true
38769
+ */
38770
+ this.isResizable = true;
38771
+ /**
38772
+ * Minimum window width (in pixels) required for resizable grid to be active.
38773
+ * Below this width, the component switches to a stacked mobile layout.
38774
+ * @default 991
38775
+ */
38776
+ this.resizableBreakpoint = 991;
38777
+ /**
38778
+ * Emits when the selected item changes.
38779
+ * The event emits the selected item or `null` when selection is cleared.
38780
+ *
38781
+ * @example
38782
+ * ```html
38783
+ * <c8y-sv (selectionChange)="onSelectionChange($event)">
38784
+ * ```
38785
+ *
38786
+ * ```typescript
38787
+ * onSelectionChange(item: Device | null) {
38788
+ * this.selectedItem = item || undefined;
38789
+ * }
38790
+ * ```
38791
+ */
38792
+ this.selectionChange = new EventEmitter();
38793
+ /**
38794
+ * Internal flag to track if current viewport width allows resizable grid
38795
+ */
38796
+ this._isResizableAtCurrentWidth = true;
38797
+ this._resizableConfig = {};
38798
+ this._memoizedResizableConfig = {
38799
+ collapseThreshold: DEFAULT_RESIZABLE_CONFIG.collapseThreshold,
38800
+ leftColumnWidth: DEFAULT_RESIZABLE_CONFIG.leftColumnWidth,
38801
+ trackId: DEFAULT_RESIZABLE_CONFIG.trackId,
38802
+ collapsible: DEFAULT_RESIZABLE_CONFIG.collapsible
38803
+ };
38804
+ this._checkViewportWidth();
38805
+ }
38806
+ ngOnInit() {
38807
+ // Subscribe to selection changes and emit them
38808
+ // Ignore the initial BehaviorSubject emission (null) so consumers only see
38809
+ // real selection changes triggered by user interaction or inputs.
38810
+ this.selectionService.selectedItem$
38811
+ .pipe(skip$1(1), takeUntilDestroyed(this.destroyRef))
38812
+ .subscribe(item => {
38813
+ this.selectionChange.emit(item);
38814
+ });
38815
+ // Set initial selection if provided
38816
+ if (this.initialSelection) {
38817
+ this.selectionService.select(this.initialSelection);
38818
+ }
38819
+ // Debounced resize listener to prevent excessive change detection
38820
+ fromEvent(window, 'resize')
38821
+ .pipe(debounceTime$1(200), takeUntilDestroyed(this.destroyRef))
38822
+ .subscribe(() => {
38823
+ this._checkViewportWidth();
38824
+ });
38825
+ }
38826
+ ngOnDestroy() {
38827
+ this.selectionChange.complete();
38828
+ }
38829
+ /**
38830
+ * Checks if a details component is projected.
38831
+ *
38832
+ * Returns `true` when `<c8y-sv-details>` is present in the template.
38833
+ * Returns `false` when `<c8y-sv-details>` is not present.
38834
+ *
38835
+ * @internal Used by the template to determine layout mode
38836
+ */
38837
+ get hasProjectedDetails() {
38838
+ return !!this._detailsComp;
38839
+ }
38840
+ /**
38841
+ * Determines if the resizable grid should be active.
38842
+ *
38843
+ * Returns `true` when all conditions are met:
38844
+ * - `isResizable` is `true`
38845
+ * - Current viewport width is above `resizableBreakpoint`
38846
+ * - Details component is projected
38847
+ *
38848
+ * When `false`, falls back to CSS-based responsive layout.
38849
+ *
38850
+ * @internal Used by the template to conditionally render resizable grid
38851
+ */
38852
+ get shouldUseResizableGrid() {
38853
+ return this.isResizable && this._isResizableAtCurrentWidth && this.hasProjectedDetails;
38854
+ }
38855
+ /**
38856
+ * Returns the effective resizable configuration with all defaults applied.
38857
+ * The configuration is memoized and updated only when inputs change.
38858
+ *
38859
+ * @internal Used by the template to pass config to resizable-grid component
38860
+ */
38861
+ get effectiveResizableConfig() {
38862
+ return this._memoizedResizableConfig;
38863
+ }
38864
+ /**
38865
+ * Returns CSS classes for the split view container element.
38866
+ *
38867
+ * Always includes: `['card', 'content-fullpage', 'grid__row--1']`
38868
+ *
38869
+ * Conditionally adds `'split-view--5-7'` when:
38870
+ * - Details component is projected
38871
+ * - Resizable grid is not active (below breakpoint or disabled)
38872
+ *
38873
+ * @returns Array of CSS class names
38874
+ */
38875
+ getContainerClasses() {
38876
+ const classes = ['card', 'content-fullpage', 'grid__row--1'];
38877
+ if (this.hasProjectedDetails && (!this.isResizable || !this._isResizableAtCurrentWidth)) {
38878
+ classes.push('split-view--5-7');
38879
+ }
38880
+ return classes;
38881
+ }
38882
+ _checkViewportWidth() {
38883
+ this._isResizableAtCurrentWidth = window.innerWidth > this.resizableBreakpoint;
38884
+ }
38885
+ updateMemoizedResizableConfig() {
38886
+ const collapseThreshold = this._resizableConfig.collapseThreshold ?? DEFAULT_RESIZABLE_CONFIG.collapseThreshold;
38887
+ const leftColumnWidth = this._resizableConfig.leftColumnWidth ?? DEFAULT_RESIZABLE_CONFIG.leftColumnWidth;
38888
+ const trackId = this._resizableConfig.trackId ?? DEFAULT_RESIZABLE_CONFIG.trackId;
38889
+ const collapsible = this._resizableConfig.collapsible ?? DEFAULT_RESIZABLE_CONFIG.collapsible;
38890
+ const current = this._memoizedResizableConfig;
38891
+ if (current.collapseThreshold !== collapseThreshold ||
38892
+ current.leftColumnWidth !== leftColumnWidth ||
38893
+ current.trackId !== trackId ||
38894
+ current.collapsible !== collapsible) {
38895
+ this._memoizedResizableConfig = { collapseThreshold, leftColumnWidth, trackId, collapsible };
38896
+ }
38897
+ }
38898
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewComponent, deps: [{ token: SplitViewSelectionService }], target: i0.ɵɵFactoryTarget.Component }); }
38899
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SplitViewComponent, isStandalone: true, selector: "c8y-sv", inputs: { showDefaultRouterOutlet: "showDefaultRouterOutlet", isResizable: "isResizable", initialSelection: "initialSelection", resizableBreakpoint: "resizableBreakpoint", resizableConfig: "resizableConfig" }, outputs: { selectionChange: "selectionChange" }, providers: [SplitViewSelectionService], queries: [{ propertyName: "_detailsComp", first: true, predicate: SplitViewDetailsComponent, descendants: true }], ngImport: i0, template: "<div\n [attr.aria-label]=\"'Split view interface' | translate\"\n tabindex=\"-1\"\n role=\"main\"\n [ngClass]=\"getContainerClasses()\"\n data-cy=\"c8y-sv\"\n>\n @if (shouldUseResizableGrid) {\n <c8y-resizable-grid\n [collapseThreshold]=\"effectiveResizableConfig.collapseThreshold\"\n [collapsible]=\"effectiveResizableConfig.collapsible\"\n [leftColumnWidth]=\"effectiveResizableConfig.leftColumnWidth\"\n [trackId]=\"effectiveResizableConfig.trackId\"\n >\n <div left-pane>\n <ng-container *ngTemplateOutlet=\"listContent\"></ng-container>\n </div>\n <div right-pane>\n <ng-container *ngTemplateOutlet=\"detailsContent\"></ng-container>\n </div>\n </c8y-resizable-grid>\n } @else {\n <ng-container *ngTemplateOutlet=\"listContent\"></ng-container>\n <ng-container *ngTemplateOutlet=\"detailsContent\"></ng-container>\n @if (showDefaultRouterOutlet && !hasProjectedDetails) {\n <router-outlet class=\"d-contents\"></router-outlet>\n }\n }\n\n <ng-template #listContent>\n <ng-content select=\":not(c8y-sv-details)\"></ng-content>\n </ng-template>\n\n <ng-template #detailsContent>\n @if (hasProjectedDetails) {\n <ng-content select=\"c8y-sv-details\"></ng-content>\n }\n </ng-template>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule$1 }, { kind: "directive", type: i1$a.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$a.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: ResizableGridComponent, selector: "c8y-resizable-grid", inputs: ["leftColumnWidth", "trackId", "collapseThreshold", "collapsible"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
38900
+ }
38901
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewComponent, decorators: [{
38902
+ type: Component,
38903
+ args: [{ selector: 'c8y-sv', standalone: true, imports: [CommonModule$1, RouterOutlet, C8yTranslatePipe, ResizableGridComponent], providers: [SplitViewSelectionService], template: "<div\n [attr.aria-label]=\"'Split view interface' | translate\"\n tabindex=\"-1\"\n role=\"main\"\n [ngClass]=\"getContainerClasses()\"\n data-cy=\"c8y-sv\"\n>\n @if (shouldUseResizableGrid) {\n <c8y-resizable-grid\n [collapseThreshold]=\"effectiveResizableConfig.collapseThreshold\"\n [collapsible]=\"effectiveResizableConfig.collapsible\"\n [leftColumnWidth]=\"effectiveResizableConfig.leftColumnWidth\"\n [trackId]=\"effectiveResizableConfig.trackId\"\n >\n <div left-pane>\n <ng-container *ngTemplateOutlet=\"listContent\"></ng-container>\n </div>\n <div right-pane>\n <ng-container *ngTemplateOutlet=\"detailsContent\"></ng-container>\n </div>\n </c8y-resizable-grid>\n } @else {\n <ng-container *ngTemplateOutlet=\"listContent\"></ng-container>\n <ng-container *ngTemplateOutlet=\"detailsContent\"></ng-container>\n @if (showDefaultRouterOutlet && !hasProjectedDetails) {\n <router-outlet class=\"d-contents\"></router-outlet>\n }\n }\n\n <ng-template #listContent>\n <ng-content select=\":not(c8y-sv-details)\"></ng-content>\n </ng-template>\n\n <ng-template #detailsContent>\n @if (hasProjectedDetails) {\n <ng-content select=\"c8y-sv-details\"></ng-content>\n }\n </ng-template>\n</div>\n" }]
38904
+ }], ctorParameters: () => [{ type: SplitViewSelectionService }], propDecorators: { showDefaultRouterOutlet: [{
38905
+ type: Input
38906
+ }], isResizable: [{
38907
+ type: Input
38908
+ }], initialSelection: [{
38909
+ type: Input
38910
+ }], resizableBreakpoint: [{
38911
+ type: Input
38912
+ }], selectionChange: [{
38913
+ type: Output
38914
+ }], resizableConfig: [{
38915
+ type: Input
38916
+ }], _detailsComp: [{
38917
+ type: ContentChild,
38918
+ args: [SplitViewDetailsComponent]
38919
+ }] } });
38920
+
38921
+ /**
38922
+ * Marker component for alert content in split-view lists.
38923
+ * Provides a named slot for displaying alerts above the list items.
38924
+ *
38925
+ * The parent split-view-list component detects this component via @ContentChild
38926
+ * and conditionally renders the alert section when present.
38927
+ *
38928
+ * This is a purely structural component with no logic or styling - all content
38929
+ * is projected and styled by the consumer.
38930
+ *
38931
+ * @example
38932
+ * ```html
38933
+ * <c8y-sv-list [title]="'Alarms'">
38934
+ * <c8y-sv-alerts>
38935
+ * @if (hasWarning) {
38936
+ * <div class="alert alert-warning" role="alert">
38937
+ * The selected item is not currently in the list.
38938
+ * </div>
38939
+ * }
38940
+ * </c8y-sv-alerts>
38941
+ * <!-- list items -->
38942
+ * @for (item of items; track item.id) {
38943
+ * <c8y-li>{{ item.name }}</c8y-li>
38944
+ * }
38945
+ * </c8y-sv-list>
38946
+ * ```
38947
+ *
38948
+ * @example Multiple alerts
38949
+ * ```html
38950
+ * <c8y-sv-list [title]="'Items'">
38951
+ * <c8y-sv-alerts>
38952
+ * @if (hasInfo) {
38953
+ * <div class="alert alert-info" role="alert">
38954
+ * Information message
38955
+ * </div>
38956
+ * }
38957
+ * @if (hasWarning) {
38958
+ * <div class="alert alert-warning" role="alert">
38959
+ * Warning message
38960
+ * </div>
38961
+ * }
38962
+ * </c8y-sv-alerts>
38963
+ * <!-- list content -->
38964
+ * </c8y-sv-list>
38965
+ * ```
38966
+ */
38967
+ class SplitViewAlertsComponent {
38968
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewAlertsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
38969
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SplitViewAlertsComponent, isStandalone: true, selector: "c8y-sv-alerts", ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
38970
+ }
38971
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewAlertsComponent, decorators: [{
38972
+ type: Component,
38973
+ args: [{
38974
+ selector: 'c8y-sv-alerts',
38975
+ template: `<ng-content></ng-content>`,
38976
+ standalone: true
38977
+ }]
38978
+ }] });
38979
+
38980
+ class SplitViewListComponent {
38981
+ constructor() {
38982
+ /**
38983
+ * Optional parent split view component.
38984
+ * Used to determine if a details panel is present for automatic background styling.
38985
+ */
38986
+ this.parentSplitView = inject(SplitViewComponent, { optional: true });
38987
+ /**
38988
+ * Title for the list section.
38989
+ * Also used as aria-label if provided.
38990
+ */
38991
+ this.title = gettext$1('Split view list');
38992
+ /**
38993
+ * Whether the list is currently loading
38994
+ */
38995
+ this.loading = false;
38996
+ /**
38997
+ * Whether to show empty state
38998
+ */
38999
+ this.showEmptyState = true;
39000
+ /**
39001
+ * Custom empty state icon
39002
+ */
39003
+ this.emptyStateIcon = 'c8y-alert-idle';
39004
+ /**
39005
+ * Custom empty state title
39006
+ */
39007
+ this.emptyStateTitle = gettext$1('No items to display.');
39008
+ /**
39009
+ * Opacity for the list content (CSS opacity: 0-1 scale).
39010
+ *
39011
+ * Use this to dim the list during loading states while showing a loading indicator.
39012
+ * Defaults to 1 (fully opaque).
39013
+ *
39014
+ * @example
39015
+ * ```html
39016
+ * <!-- Dim list to 20% opacity during initial load -->
39017
+ * <c8y-sv-list [listOpacity]="isLoading ? 0.2 : 1">
39018
+ * ```
39019
+ */
39020
+ this.listOpacity = 1;
39021
+ }
39022
+ get hasAlerts() {
39023
+ return !!this.alertsComp;
39024
+ }
39025
+ /**
39026
+ * Computed property that determines if the title should be shown.
39027
+ * Uses the explicit `showTitle` input if provided, otherwise falls back to automatic detection.
39028
+ *
39029
+ * Automatic detection logic:
39030
+ * - Inside `<c8y-sv>`: shows the title (full page context)
39031
+ * - Outside `<c8y-sv>`: hides the title (widget context where widget provides its own title bar)
39032
+ */
39033
+ get shouldShowTitle() {
39034
+ return this.showTitle !== undefined ? this.showTitle : !!this.parentSplitView;
39035
+ }
39036
+ /**
39037
+ * Determines if split view layout styles should be applied based on the presence of a details panel.
39038
+ *
39039
+ * When a details panel (`<c8y-sv-details>`) is present alongside the list:
39040
+ * - Returns `true` → applies `split-view__list bg-level-1` classes (lighter background for contrast)
39041
+ *
39042
+ * When no details panel is present (single column or widget usage):
39043
+ * - Returns `false` → applies `bg-component` class (standard component background)
39044
+ *
39045
+ * This detection is automatic and based on the actual layout structure.
39046
+ */
39047
+ get isSplitView() {
39048
+ return !!this.parentSplitView?.hasProjectedDetails;
39049
+ }
39050
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
39051
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SplitViewListComponent, isStandalone: true, selector: "c8y-sv-list", inputs: { title: "title", loading: "loading", showEmptyState: "showEmptyState", emptyStateIcon: "emptyStateIcon", emptyStateTitle: "emptyStateTitle", emptyStateSubtitle: "emptyStateSubtitle", docsUrl: "docsUrl", showTitle: "showTitle", listOpacity: "listOpacity" }, host: { classAttribute: "d-contents" }, queries: [{ propertyName: "alertsComp", first: true, predicate: SplitViewAlertsComponent, descendants: true }], viewQueries: [{ propertyName: "innerScrollDiv", first: true, predicate: ["innerScrollDiv"], descendants: true }], ngImport: i0, template: "<div\n class=\"inner-scroll fit-h\"\n [attr.aria-label]=\"title | translate\"\n role=\"region\"\n [ngClass]=\"{ 'split-view__list bg-level-1': isSplitView, 'bg-component': !isSplitView }\"\n data-cy=\"c8y-sv-list\"\n #innerScrollDiv\n>\n @if (title || hasAlerts) {\n <div\n class=\"flex-wrap flex-no-shrink sticky-top gap-8\"\n [ngClass]=\"{\n 'card-header separator': title && shouldShowTitle\n }\"\n >\n @if (title && shouldShowTitle) {\n <h4 class=\"card-title\">\n {{ title | translate }}\n </h4>\n }\n <ng-content select=\"c8y-sv-header-actions\"></ng-content>\n @if (hasAlerts) {\n <ng-content select=\"c8y-sv-alerts\"></ng-content>\n }\n </div>\n }\n <div data-cy=\"c8y-sv-list--group\">\n @if (loading && !showEmptyState) {\n <div class=\"p-absolute fit-w overflow-hidden p-b-4\">\n <c8y-loading\n [layout]=\"'page'\"\n data-cy=\"c8y-sv-list--loading\"\n ></c8y-loading>\n </div>\n }\n <ng-content></ng-content>\n\n @if (showEmptyState) {\n <div class=\"p-relative p-l-24\">\n <c8y-ui-empty-state\n [icon]=\"emptyStateIcon\"\n [title]=\"emptyStateTitle\"\n [subtitle]=\"emptyStateSubtitle\"\n data-cy=\"c8y-sv-list--empty-state\"\n >\n @if (docsUrl) {\n <p>\n <small\n c8y-guide-docs\n translate\n [translateParams]=\"{ docsUrl }\"\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"{{ docsUrl }}\">user documentation</a>\n .\n </small>\n </p>\n }\n </c8y-ui-empty-state>\n </div>\n }\n </div>\n\n <ng-content select=\"c8y-sv-footer\"></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "directive", type: GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); }
39052
+ }
39053
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewListComponent, decorators: [{
39054
+ type: Component,
39055
+ args: [{ selector: 'c8y-sv-list', host: { class: 'd-contents' }, standalone: true, imports: [
39056
+ NgClass,
39057
+ LoadingComponent,
39058
+ EmptyStateComponent,
39059
+ C8yTranslatePipe,
39060
+ C8yTranslateDirective,
39061
+ GuideDocsComponent,
39062
+ GuideHrefDirective
39063
+ ], template: "<div\n class=\"inner-scroll fit-h\"\n [attr.aria-label]=\"title | translate\"\n role=\"region\"\n [ngClass]=\"{ 'split-view__list bg-level-1': isSplitView, 'bg-component': !isSplitView }\"\n data-cy=\"c8y-sv-list\"\n #innerScrollDiv\n>\n @if (title || hasAlerts) {\n <div\n class=\"flex-wrap flex-no-shrink sticky-top gap-8\"\n [ngClass]=\"{\n 'card-header separator': title && shouldShowTitle\n }\"\n >\n @if (title && shouldShowTitle) {\n <h4 class=\"card-title\">\n {{ title | translate }}\n </h4>\n }\n <ng-content select=\"c8y-sv-header-actions\"></ng-content>\n @if (hasAlerts) {\n <ng-content select=\"c8y-sv-alerts\"></ng-content>\n }\n </div>\n }\n <div data-cy=\"c8y-sv-list--group\">\n @if (loading && !showEmptyState) {\n <div class=\"p-absolute fit-w overflow-hidden p-b-4\">\n <c8y-loading\n [layout]=\"'page'\"\n data-cy=\"c8y-sv-list--loading\"\n ></c8y-loading>\n </div>\n }\n <ng-content></ng-content>\n\n @if (showEmptyState) {\n <div class=\"p-relative p-l-24\">\n <c8y-ui-empty-state\n [icon]=\"emptyStateIcon\"\n [title]=\"emptyStateTitle\"\n [subtitle]=\"emptyStateSubtitle\"\n data-cy=\"c8y-sv-list--empty-state\"\n >\n @if (docsUrl) {\n <p>\n <small\n c8y-guide-docs\n translate\n [translateParams]=\"{ docsUrl }\"\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"{{ docsUrl }}\">user documentation</a>\n .\n </small>\n </p>\n }\n </c8y-ui-empty-state>\n </div>\n }\n </div>\n\n <ng-content select=\"c8y-sv-footer\"></ng-content>\n</div>\n" }]
39064
+ }], propDecorators: { title: [{
39065
+ type: Input
39066
+ }], loading: [{
39067
+ type: Input
39068
+ }], showEmptyState: [{
39069
+ type: Input
39070
+ }], emptyStateIcon: [{
39071
+ type: Input
39072
+ }], emptyStateTitle: [{
39073
+ type: Input
39074
+ }], emptyStateSubtitle: [{
39075
+ type: Input
39076
+ }], docsUrl: [{
39077
+ type: Input
39078
+ }], showTitle: [{
39079
+ type: Input
39080
+ }], listOpacity: [{
39081
+ type: Input
39082
+ }], innerScrollDiv: [{
39083
+ type: ViewChild,
39084
+ args: ['innerScrollDiv']
39085
+ }], alertsComp: [{
39086
+ type: ContentChild,
39087
+ args: [SplitViewAlertsComponent]
39088
+ }] } });
39089
+
39090
+ class SplitViewHeaderActionsComponent {
39091
+ constructor() {
39092
+ /**
39093
+ * Parent list component reference to automatically detect if title is shown.
39094
+ * This allows automatic adjustment of spacing based on parent's showTitle setting.
39095
+ */
39096
+ this.parentList = inject(SplitViewListComponent);
39097
+ }
39098
+ /**
39099
+ * Whether the parent list shows a title.
39100
+ * Automatically inherited from parent, used to adjust spacing.
39101
+ */
39102
+ get showTitle() {
39103
+ return this.parentList.shouldShowTitle;
39104
+ }
39105
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewHeaderActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
39106
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: SplitViewHeaderActionsComponent, isStandalone: true, selector: "c8y-sv-header-actions", host: { classAttribute: "d-contents" }, ngImport: i0, template: "<div\n [ngClass]=\"{ 'd-flex a-i-center fit-w': !showTitle, 'm-l-auto': showTitle }\"\n data-cy=\"c8y-sv-header-actions\"\n>\n <ng-content></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
39107
+ }
39108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewHeaderActionsComponent, decorators: [{
39109
+ type: Component,
39110
+ args: [{ selector: 'c8y-sv-header-actions', host: { class: 'd-contents' }, standalone: true, imports: [NgClass], template: "<div\n [ngClass]=\"{ 'd-flex a-i-center fit-w': !showTitle, 'm-l-auto': showTitle }\"\n data-cy=\"c8y-sv-header-actions\"\n>\n <ng-content></ng-content>\n</div>\n" }]
39111
+ }] });
39112
+
39113
+ /**
39114
+ * Directive to handle item selection in split-view list.
39115
+ * Automatically selects the item on click and applies the 'active' class.
39116
+ *
39117
+ * Usage:
39118
+ * ```html
39119
+ * @for (device of devices; track device.id) {
39120
+ * <c8y-li [c8ySvListItem]="device">
39121
+ * {{ device.name }}
39122
+ * </c8y-li>
39123
+ * }
39124
+ * ```
39125
+ */
39126
+ class SplitViewListItemDirective {
39127
+ constructor(selectionService) {
39128
+ this.selectionService = selectionService;
39129
+ }
39130
+ get isActive() {
39131
+ return !!(this.item && this.selectionService?.isSelected(this.item));
39132
+ }
39133
+ get role() {
39134
+ return 'button';
39135
+ }
39136
+ onClick() {
39137
+ if (this.item && this.selectionService) {
39138
+ this.selectionService.select(this.item);
39139
+ }
39140
+ }
39141
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewListItemDirective, deps: [{ token: SplitViewSelectionService, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
39142
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.15", type: SplitViewListItemDirective, isStandalone: true, selector: "[c8ySvListItem]", inputs: { item: ["c8ySvListItem", "item"] }, host: { listeners: { "click": "onClick()" }, properties: { "class.active": "this.isActive", "attr.role": "this.role" }, classAttribute: "pointer" }, ngImport: i0 }); }
39143
+ }
39144
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SplitViewListItemDirective, decorators: [{
39145
+ type: Directive,
39146
+ args: [{
39147
+ selector: '[c8ySvListItem]',
39148
+ standalone: true,
39149
+ host: { class: 'pointer' }
39150
+ }]
39151
+ }], ctorParameters: () => [{ type: SplitViewSelectionService, decorators: [{
39152
+ type: Optional
39153
+ }] }], propDecorators: { item: [{
39154
+ type: Input,
39155
+ args: [{ alias: 'c8ySvListItem' }]
39156
+ }], isActive: [{
39157
+ type: HostBinding,
39158
+ args: ['class.active']
39159
+ }], role: [{
39160
+ type: HostBinding,
39161
+ args: ['attr.role']
39162
+ }], onClick: [{
39163
+ type: HostListener,
39164
+ args: ['click']
39165
+ }] } });
39166
+
38126
39167
  /**
38127
39168
  * Barrel to export /core
38128
39169
  */
@@ -38131,5 +39172,5 @@ function colorValidator(allowedModes) {
38131
39172
  * Generated bundle index. Do not edit.
38132
39173
  */
38133
39174
 
38134
- export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionControlsExtensionService, ActionModule, ActionOutletComponent, ActionService, AggregationPickerComponent, AggregationService, AlarmRealtimeService, AlarmWithChildrenRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppHrefPipe, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherInlineComponent, AppSwitcherService, ApplicationModule, ApplicationPluginStatus, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BooleanFilterMapper, BootstrapComponent, BootstrapModule, BottomDrawerComponent, BottomDrawerRef, BottomDrawerService, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BuiltInActionType, BytesPipe, C8Y_PLUGIN_CONTEXT_PATH, C8Y_PLUGIN_NAME, C8yComponentOutlet, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yTranslationCache, C8yTranslationLoader, C8yValidators, CUSTOM, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangeCurrentUserPasswordService, ChangeIconComponent, ClipboardModule, ClipboardService, ColorInputComponent, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CopyDashboardDisabledReason, CoreModule, CoreSearchModule, CountdownIntervalComponent, CountdownIntervalModule, CurrentPasswordModalComponent, CustomColumn, CustomTranslateService, CustomTranslateStore, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, DEFAULT_INTERVAL_VALUES, DRAWER_ANIMATION_TIME, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatapointSyncService, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentAlertsComponent, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EmptyStateContextDirective, EventRealtimeService, ExpandableRowDirective, ExtensionPointForPlugins, ExtensionPointWithoutStateForPlugins, ExtractArrayValidationErrorsPipe, FeatureCacheService, FeedbackFormComponent, FilePickerComponent, FilePickerFormControlComponent, FilePickerFormControlModule, FilePickerModule, FilesService, FilterByPipe, FilterInputComponent, FilterMapperFactory, FilterMapperModule, FilterMapperPipe, FilterMapperService, FilterNonArrayValidationErrorsPipe, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GLOBAL_CONTEXT_AUTO_REFRESH, GainsightService, GenericFileIconPipe, GeoService, GetGroupIconPipe, GlobalConfigService, GridDataSource, GroupFragment, GroupService, GroupedFilterChips, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_CURRENT_APPLICATION, HOOK_CURRENT_TENANT, HOOK_CURRENT_USER, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_PLUGIN, HOOK_PREVIEW, HOOK_QUERY_PARAM, HOOK_QUERY_PARAM_BOTTOM_DRAWER, HOOK_QUERY_PARAM_MODAL, HOOK_ROUTE, HOOK_SEARCH, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, HumanizeValidationMessagePipe, I18nModule, INTERVAL_OPTIONS, IconDirective, IfAllowedDirective, InjectionType, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntervalBasedReload, InventorySearchService, IpRangeInputListComponent, JsonValidationPrettifierDirective, LANGUAGES, LAST_DAY, LAST_HOUR, LAST_MINUTE, LAST_MONTH, LAST_WEEK, LOCALE_PATH, LegacyGridConfigMapperService, LegendFieldWrapper, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, MAX_PAGE_SIZE, MESSAGES_CORE_I18N, MOChunkLoaderService, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageBannerService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, MoNamePipe, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NEW_DASHBOARD_ROUTER_STATE_PROP, NULL_VALUE_PLACEHOLDER, NUMBER_FORMAT_REGEXP, NameTransformPipe, NavigatorBottomModule, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NavigatorTopModule, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PREVIEW_FEATURE_PROVIDERS, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PackageType, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordInputComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthService, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginLoadedPipe, PluginsExportScopes, PluginsLoaderService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, PreviewFeatureButtonComponent, PreviewFeatureShowNotification, PreviewService, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, PropertyValueTransformService, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QUERY_PARAM_HANDLER_PROVIDERS, QueryParamBottomDrawerFactory, QueryParamBottomDrawerStateService, QueryParamHandlerService, QueryParamModalFactory, QueryParamModalStateService, QuickLinkComponent, QuickLinkModule, RESOLVING_COMPONENT_WAIT_TIME, RadioFilterMapper, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeControlComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RelativeTimePipe, RequiredInputPlaceholderDirective, ResizableGridComponent, ResolverServerError, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SHOW_PREVIEW_FEATURES, SearchComponent, SearchFilters, SearchInputComponent, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent, SelectFilterMapper, SelectItemDirective, SelectKeyboardService, SelectLegacyComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SelectedItemsComponent, SelectedItemsDirective, SendStatus, SendStatusLabels, ServiceRegistry, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SimplifiedAuthService, SkipLinkDirective, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StringFilterMapper, StringifyObjectPipe, SupportedApps, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, ThemeSwitcherService, TimeIntervalComponent, TimePickerComponent, TimePickerModule, TitleComponent, TitleOutletComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TreeNodeCellRendererComponent, TreeNodeColumn, TreeNodeHeaderCellRendererComponent, TypeaheadComponent, TypeaheadFilterMapper, UiSettingsComponent, UiSettingsModule, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserEngagementsService, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, colorValidator, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getDictionaryWithTrimmedKeys, getInjectedHooks, gettext, globalAutoRefreshLoading, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookCurrentApplication, hookCurrentTenant, hookCurrentUser, hookDataGridActionControls, hookDocs, hookDrawer, hookDynamicProviderConfig, hookFilterMapper, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookPlugin, hookPreview, hookQueryParam, hookQueryParamBottomDrawer, hookQueryParamModal, hookRoute, hookSearch, hookService, hookStepper, hookTab, hookUserMenu, hookVersion, hookWidget, hookWizard, internalApps, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
39175
+ export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AbstractConfigurationStrategy, ActionBarComponent, ActionBarItemComponent, ActionBarModule, ActionBarService, ActionComponent, ActionControlsExtensionService, ActionModule, ActionOutletComponent, ActionService, AggregationPickerComponent, AggregationService, AlarmRealtimeService, AlarmWithChildrenRealtimeService, AlertComponent, AlertDetailsComponent, AlertModule, AlertOutletBase, AlertOutletComponent, AlertService, AlertTextComponent, AppHrefPipe, AppIconComponent, AppStateService, AppSwitcherComponent, AppSwitcherInlineComponent, AppSwitcherService, ApplicationModule, ApplicationPluginStatus, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BackendVersionFactory, BaseColumn, BaseFilteringFormRendererComponent, BooleanFilterMapper, BootstrapComponent, BootstrapModule, BottomDrawerComponent, BottomDrawerRef, BottomDrawerService, BreadcrumbComponent, BreadcrumbItemComponent, BreadcrumbModule, BreadcrumbOutletComponent, BreadcrumbService, BuiltInActionType, BytesPipe, C8Y_PLUGIN_CONTEXT_PATH, C8Y_PLUGIN_NAME, C8yComponentOutlet, C8yJSONSchema, C8yStepper, C8yStepperButtons, C8yStepperIcon, C8yStepperProgress, C8yTranslateDirective, C8yTranslateModule, C8yTranslatePipe, C8yTranslationCache, C8yTranslationLoader, C8yValidators, CUSTOM, CachedLocaleDictionaryService, CellRendererComponent, CellRendererContext, CellRendererDefDirective, ChangeCurrentUserPasswordService, ChangeIconComponent, ClipboardModule, ClipboardService, ColorInputComponent, ColorService, ColumnDirective, CommonModule, ConditionalTabsOutletComponent, ConfigureCustomColumnComponent, ConfirmModalComponent, ContextRouteComponent, ContextRouteGuard, ContextRouteService, CookieBannerComponent, CopyDashboardDisabledReason, CoreModule, CoreSearchModule, CountdownIntervalComponent, CountdownIntervalModule, CurrentPasswordModalComponent, CustomColumn, CustomTranslateService, CustomTranslateStore, DATA_GRID_CONFIGURATION_CONTEXT, DATA_GRID_CONFIGURATION_CONTEXT_PROVIDER, DATA_GRID_CONFIGURATION_STRATEGY, DEFAULT_INTERVAL_STATE, DEFAULT_INTERVAL_VALUE, DEFAULT_INTERVAL_VALUES, DRAWER_ANIMATION_TIME, DashboardChildActionComponent, DashboardChildChange, DashboardChildComponent, DashboardChildTitleComponent, DashboardComponent, DashboardModule, DataGridComponent, DataGridModule, DataGridService, DatapointLibraryValidationErrors, DatapointSyncService, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DynamicBulkDetailsResolver, DynamicBulkIIdentifiedResolver, DynamicComponentAlert, DynamicComponentAlertAggregator, DynamicComponentAlertsComponent, DynamicComponentComponent, DynamicComponentErrorStrategy, DynamicComponentModule, DynamicComponentService, DynamicDatapointsResolver, DynamicFormsModule, DynamicManagedObjectResolver, DynamicResolverService, ES_MAX_TIME_MILLISECONDS, EmailsValidatorDirective, EmptyComponent, EmptyStateComponent, EmptyStateContextDirective, EventRealtimeService, ExpandableRowDirective, ExtensionPointForPlugins, ExtensionPointWithoutStateForPlugins, ExtractArrayValidationErrorsPipe, FeatureCacheService, FeedbackFormComponent, FilePickerComponent, FilePickerFormControlComponent, FilePickerFormControlModule, FilePickerModule, FilesService, FilterByPipe, FilterInputComponent, FilterMapperFactory, FilterMapperModule, FilterMapperPipe, FilterMapperService, FilterNonArrayValidationErrorsPipe, FilteringActionType, FilteringFormRendererComponent, FilteringFormRendererContext, FilteringFormRendererDefDirective, ForOfDirective, FormGroupComponent, FormsModule, GENERIC_FILE_TYPE, GLOBAL_CONTEXT_AUTO_REFRESH, GainsightService, GenericFileIconPipe, GeoService, GetGroupIconPipe, GlobalConfigService, GridDataSource, GroupFragment, GroupService, GroupedFilterChips, GuideDocsComponent, GuideHrefDirective, HOOK_ACTION, HOOK_ACTION_BAR, HOOK_BREADCRUMB, HOOK_COMPONENTS, HOOK_CURRENT_APPLICATION, HOOK_CURRENT_TENANT, HOOK_CURRENT_USER, HOOK_DOCS, HOOK_DYNAMIC_PROVIDER_CONFIG, HOOK_NAVIGATOR_NODES, HOOK_OPTIONS, HOOK_PATTERN_MESSAGES, HOOK_PLUGIN, HOOK_PREVIEW, HOOK_QUERY_PARAM, HOOK_QUERY_PARAM_BOTTOM_DRAWER, HOOK_QUERY_PARAM_MODAL, HOOK_ROUTE, HOOK_SEARCH, HOOK_STEPPER, HOOK_TABS, HOOK_VERSION, HOOK_WIZARD, HeaderBarComponent, HeaderCellRendererDefDirective, HeaderModule, HeaderService, HelpComponent, HelpModule, HighlightComponent, HookProviderTypes, HumanizeAppNamePipe, HumanizePipe, HumanizeValidationMessagePipe, I18nModule, INTERVAL_OPTIONS, IconDirective, IconPanelComponent, IfAllowedDirective, InjectionType, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntervalBasedReload, InventorySearchService, IpRangeInputListComponent, JsonValidationPrettifierDirective, LANGUAGES, LAST_DAY, LAST_HOUR, LAST_MINUTE, LAST_MONTH, LAST_WEEK, LOCALE_PATH, LegacyGridConfigMapperService, LegendFieldWrapper, ListDisplaySwitchComponent, ListDisplaySwitchModule, ListGroupComponent, ListGroupModule, ListItemActionComponent, ListItemBodyComponent, ListItemCheckboxComponent, ListItemCollapseComponent, ListItemComponent, ListItemDragHandleComponent, ListItemFooterComponent, ListItemIconComponent, ListItemRadioComponent, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, MAX_PAGE_SIZE, MESSAGES_CORE_I18N, MOChunkLoaderService, ManagedObjectRealtimeService, ManagedObjectType, MapFunctionPipe, MarkdownToHtmlPipe, MaxValidationDirective, MeasurementRealtimeService, MessageBannerService, MessageDirective, MessagesComponent, MinValidationDirective, MissingTranslationCustomHandler, MoNamePipe, ModalComponent, ModalModule, ModalSelectionMode, ModalService, NEEDED_ROLE_FOR_SETUP, NEW_DASHBOARD_ROUTER_STATE_PROP, NULL_VALUE_PLACEHOLDER, NUMBER_FORMAT_REGEXP, NameTransformPipe, NavigatorBottomModule, NavigatorIconComponent, NavigatorModule, NavigatorNode, NavigatorNodeComponent, NavigatorNodeRoot, NavigatorOutletComponent, NavigatorService, NavigatorTopModule, NewPasswordComponent, NumberPipe, OperationBulkRealtimeService, OperationRealtimeService, OperationResultComponent, OptionsService, OutletDirective, PREVIEW_FEATURE_PROVIDERS, PRODUCT_EXPERIENCE_EVENT_SOURCE, PX_ACTIONS, PX_EVENT_NAME, PackageType, PasswordCheckListComponent, PasswordConfirm, PasswordConfirmModalComponent, PasswordInputComponent, PasswordService, PasswordStrengthCheckerService, PasswordStrengthComponent, PasswordStrengthService, PatternMessagesService, Permissions, PhoneValidationDirective, PlatformDetailsService, PluginLoadedPipe, PluginsExportScopes, PluginsLoaderService, PluginsModule, PluginsResolveService, PluginsService, PopoverConfirmComponent, PreviewFeatureButtonComponent, PreviewFeatureShowNotification, PreviewService, ProductExperienceDirective, ProductExperienceModule, ProgressBarComponent, PropertiesListComponent, PropertiesListModule, PropertyValueTransformService, ProviderConfigurationComponent, ProviderConfigurationModule, ProviderConfigurationNodeFactory, ProviderConfigurationRouteFactory, ProviderConfigurationService, ProviderDefinitionsService, PushStatus, PushStatusLabels, QUERY_PARAM_HANDLER_PROVIDERS, QueryParamBottomDrawerFactory, QueryParamBottomDrawerStateService, QueryParamHandlerService, QueryParamModalFactory, QueryParamModalStateService, QuickLinkComponent, QuickLinkModule, RESOLVING_COMPONENT_WAIT_TIME, RadioFilterMapper, RangeComponent, RangeDirective, RangeDisplayComponent, RangeDisplayModule, RealtimeButtonComponent, RealtimeControlComponent, RealtimeMessage, RealtimeModule, RealtimeService, RealtimeSubjectService, RelativeTimePipe, RequiredInputPlaceholderDirective, ResizableGridComponent, ResolverServerError, RouterModule, RouterService, RouterTabsResolver, SETUP_FINISHED_STEP_ID, SHOW_PREVIEW_FEATURES, SearchComponent, SearchFilters, SearchInputComponent, SearchOutletComponent, SearchResultEmptyComponent, SearchService, SelectComponent, SelectFilterMapper, SelectItemDirective, SelectKeyboardService, SelectLegacyComponent, SelectModalComponent, SelectModalFilterPipe, SelectModalModule, SelectModule, SelectedItemsComponent, SelectedItemsDirective, SendStatus, SendStatusLabels, ServiceRegistry, SetupCompletedComponent, SetupComponent, SetupModule, SetupService, SetupState, SetupStepperFactory, ShortenUserNamePipe, ShouldShowMoPipe, ShowIfFilterPipe, SimpleJsonPathValidatorDirective, SimplifiedAuthService, SkipLinkDirective, SplitViewAlertsComponent, SplitViewComponent, SplitViewDetailsActionsComponent, SplitViewDetailsComponent, SplitViewExtraHeaderComponent, SplitViewFooterComponent, SplitViewHeaderActionsComponent, SplitViewListComponent, SplitViewListItemDirective, SplitViewSelectionService, StateService, Status, StepperModule, StepperOutletComponent, StepperService, Steppers, StringFilterMapper, StringifyObjectPipe, StripHtmlPipe, SupportedApps, TabComponent, TabsModule, TabsOutletComponent, TabsService, TabsetAriaDirective, TenantUiService, TextAreaRowHeightDirective, TextareaAutoresizeDirective, ThemeSwitcherService, TimeIntervalComponent, TimePickerComponent, TimePickerModule, TitleComponent, TitleOutletComponent, TotpChallengeComponent, TotpSetupComponent, TranslateService, TreeNodeCellRendererComponent, TreeNodeColumn, TreeNodeHeaderCellRendererComponent, TypeaheadComponent, TypeaheadFilterMapper, UiSettingsComponent, UiSettingsModule, UniqueInCollectionByPathValidationDirective, UserEditComponent, UserEditModalComponent, UserEngagementsService, UserMenuItemComponent, UserMenuOutletComponent, UserMenuService, UserModule, UserNameInitialsPipe, UserPreferencesConfigurationStrategy, UserPreferencesService, UserPreferencesStorageInventory, UserPreferencesStorageLocal, UserTotpRevokeComponent, UserTotpSetupComponent, VERSION_MODULE_CONFIG, ValidationPattern, VersionListComponent, VersionModule, VersionService, ViewContext, ViewContextServices, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, colorValidator, deviceAvailabilityIconMap, extraRoutes, fromFactories, fromTrigger, fromTriggerOnce, getActivatedRoute, getAngularLocalesLanguageString, getBasicInputArrayFormFieldConfig, getDictionaryWithTrimmedKeys, getInjectedHooks, gettext, globalAutoRefreshLoading, hookAction, hookActionBar, hookBreadcrumb, hookComponent, hookCurrentApplication, hookCurrentTenant, hookCurrentUser, hookDataGridActionControls, hookDocs, hookDrawer, hookDynamicProviderConfig, hookFilterMapper, hookGeneric, hookNavigator, hookOptions, hookPatternMessages, hookPlugin, hookPreview, hookQueryParam, hookQueryParamBottomDrawer, hookQueryParamModal, hookRoute, hookSearch, hookService, hookStepper, hookTab, hookUserMenu, hookVersion, hookWidget, hookWizard, internalApps, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
38135
39176
  //# sourceMappingURL=c8y-ngx-components.mjs.map