@c8y/ngx-components 1024.16.21 → 1024.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +14 -4
  2. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
  3. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +1 -1
  4. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  5. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +1 -1
  6. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-repository-configuration.mjs +77 -20
  8. package/fesm2022/c8y-ngx-components-repository-configuration.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-notes.mjs +29 -7
  10. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-notes.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +24 -24
  12. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs +1 -1
  14. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components.mjs +159 -75
  16. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  17. package/locales/locales.pot +31 -17
  18. package/package.json +1 -1
  19. package/types/c8y-ngx-components-ai-agent-chat.d.ts +8 -1
  20. package/types/c8y-ngx-components-ai-agent-chat.d.ts.map +1 -1
  21. package/types/c8y-ngx-components-repository-configuration.d.ts +20 -4
  22. package/types/c8y-ngx-components-repository-configuration.d.ts.map +1 -1
  23. package/types/c8y-ngx-components-widgets-implementations-asset-notes.d.ts +7 -0
  24. package/types/c8y-ngx-components-widgets-implementations-asset-notes.d.ts.map +1 -1
  25. package/types/c8y-ngx-components.d.ts +80 -23
  26. package/types/c8y-ngx-components.d.ts.map +1 -1
@@ -8297,7 +8297,7 @@ class StringifyObjectPipe {
8297
8297
  this.isoDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(([+-](\d{2}):(\d{2})|Z)?)$/;
8298
8298
  }
8299
8299
  transform(value) {
8300
- if (!value) {
8300
+ if (value === null || value === undefined || value === '') {
8301
8301
  return '';
8302
8302
  }
8303
8303
  if (typeof value === 'object' && !isDate(value)) {
@@ -40002,7 +40002,8 @@ class RealtimeMessage {
40002
40002
  /**
40003
40003
  * Resizable Grid Component
40004
40004
  *
40005
- * Provides a flexible layout with two adjustable columns separated by a draggable divider.
40005
+ * Provides a flexible layout with two adjustable panes separated by a draggable divider.
40006
+ * Supports both a horizontal (left/right) and a vertical (top/bottom) split.
40006
40007
  *
40007
40008
  * ## Basic Usage
40008
40009
  *
@@ -40016,17 +40017,42 @@ class RealtimeMessage {
40016
40017
  * <div #colB>Right column content</div>
40017
40018
  * </c8y-resizable-grid>
40018
40019
  * ```
40020
+ *
40021
+ * ## Vertical (top/bottom) split
40022
+ *
40023
+ * ```html
40024
+ * <c8y-resizable-grid
40025
+ * [orientation]="'vertical'"
40026
+ * [leftColumnWidth]="'40%'">
40027
+ * <div #colA>Top pane content</div>
40028
+ * <div #colB>Bottom pane content</div>
40029
+ * </c8y-resizable-grid>
40030
+ * ```
40019
40031
  */
40020
40032
  class ResizableGridComponent {
40033
+ /**
40034
+ * Whether the grid splits panes top/bottom instead of left/right.
40035
+ * @internal Used by the template and internal size calculations.
40036
+ */
40037
+ get isVertical() {
40038
+ return this.orientation === 'vertical';
40039
+ }
40040
+ get _colAHeight() {
40041
+ return this._colAWidth;
40042
+ }
40021
40043
  /**
40022
40044
  * Public getter for aria-valuenow
40023
40045
  */
40024
40046
  get colAWidthPercent() {
40025
40047
  if (!this.colA || !this.colA.nativeElement.parentElement)
40026
40048
  return 50; // Default or fallback
40027
- const totalWidth = this.colA.nativeElement.parentElement.offsetWidth;
40028
- const currentWidth = this.colA.nativeElement.offsetWidth;
40029
- return totalWidth > 0 ? Math.round((currentWidth / totalWidth) * 100) : 0;
40049
+ const totalSize = this.isVertical
40050
+ ? this.colA.nativeElement.parentElement.offsetHeight
40051
+ : this.colA.nativeElement.parentElement.offsetWidth;
40052
+ const currentSize = this.isVertical
40053
+ ? this.colA.nativeElement.offsetHeight
40054
+ : this.colA.nativeElement.offsetWidth;
40055
+ return totalSize > 0 ? Math.round((currentSize / totalSize) * 100) : 0;
40030
40056
  }
40031
40057
  /**
40032
40058
  * Creates an instance of ResizableGridComponent.
@@ -40035,40 +40061,47 @@ class ResizableGridComponent {
40035
40061
  constructor(renderer) {
40036
40062
  this.renderer = renderer;
40037
40063
  /**
40038
- * Initial width of the left column (A). Can be any valid CSS width value (e.g., '50%', '300px').
40064
+ * Initial size of pane A along the resize axis. Can be any valid CSS size value (e.g., '50%', '300px').
40065
+ * Applies to width when `orientation` is `'horizontal'`, and to height when it is `'vertical'`.
40039
40066
  */
40040
40067
  this.leftColumnWidth = '50%';
40041
40068
  /**
40042
- * Optional key for localStorage to persist the left column width between sessions.
40069
+ * Optional key for localStorage to persist pane A's size between sessions.
40043
40070
  */
40044
40071
  this.trackId = null;
40045
40072
  /**
40046
- * Minimum width (in pixels) before a column is considered collapsed.
40073
+ * Minimum size (in pixels) before a pane is considered collapsed.
40047
40074
  */
40048
40075
  this.collapseThreshold = 320;
40049
40076
  /**
40050
- * If true, columns can collapse below the threshold. If false, columns stop at the threshold.
40077
+ * If true, panes can collapse below the threshold. If false, panes stop at the threshold.
40051
40078
  */
40052
40079
  this.collapsible = true;
40080
+ /**
40081
+ * Split direction of the grid.
40082
+ * - `'horizontal'`: panes side by side (left/right), draggable vertical divider. (default)
40083
+ * - `'vertical'`: panes stacked (top/bottom), draggable horizontal divider.
40084
+ */
40085
+ this.orientation = 'horizontal';
40053
40086
  /**
40054
40087
  * True if the user is currently resizing the grid.
40055
40088
  */
40056
40089
  this.isResizing = false;
40057
40090
  /**
40058
- * CSS width value for the left column (A).
40059
- * Used for dynamic styling via HostBinding.
40091
+ * CSS size value for pane A along the resize axis.
40092
+ * Bound to both `--col-a-width` and `--col-a-height` so either orientation's stylesheet can consume it.
40060
40093
  */
40061
40094
  this._colAWidth = '50%';
40062
40095
  /**
40063
- * X position of the mouse when resizing starts.
40096
+ * Mouse position (X for horizontal, Y for vertical) when resizing starts.
40064
40097
  */
40065
- this.startX = 0;
40098
+ this.startPos = 0;
40066
40099
  /**
40067
- * Pixel width of column A when resizing starts.
40100
+ * Pixel size of pane A when resizing starts.
40068
40101
  */
40069
- this.startColAWidthPx = 0;
40102
+ this.startColASizePx = 0;
40070
40103
  /**
40071
- * Last known non-collapsed width of column A (for restore logic).
40104
+ * Last known non-collapsed size of pane A (for restore logic).
40072
40105
  */
40073
40106
  this.lastKnownNonCollapsedWidth = null;
40074
40107
  this.resizeStep = 10; // Pixels to move with arrow keys
@@ -40112,9 +40145,9 @@ class ResizableGridComponent {
40112
40145
  }
40113
40146
  event.preventDefault();
40114
40147
  this.isResizing = true;
40115
- this.startX = event.clientX;
40116
- this.startColAWidthPx = this.colA.nativeElement.offsetWidth;
40117
- this.renderer.setStyle(document.body, 'cursor', 'col-resize');
40148
+ this.startPos = this.isVertical ? event.clientY : event.clientX;
40149
+ this.startColASizePx = this.getElementSize(this.colA.nativeElement);
40150
+ this.renderer.setStyle(document.body, 'cursor', this.isVertical ? 'row-resize' : 'col-resize');
40118
40151
  this.renderer.addClass(document.body, 'no-select');
40119
40152
  // Store the current _colAWidth as the starting point for lastKnownNonCollapsedWidth
40120
40153
  // before we potentially remove collapse classes.
@@ -40139,8 +40172,9 @@ class ResizableGridComponent {
40139
40172
  if (!this.isResizing || !this.colA || !this.colB) {
40140
40173
  return;
40141
40174
  }
40142
- const deltaX = event.clientX - this.startX;
40143
- this.updateColumnWidth(this.startColAWidthPx + deltaX);
40175
+ const currentPos = this.isVertical ? event.clientY : event.clientX;
40176
+ const delta = currentPos - this.startPos;
40177
+ this.updateColumnWidth(this.startColASizePx + delta);
40144
40178
  }
40145
40179
  /**
40146
40180
  * Mouse up event handler for ending resize and applying collapse logic.
@@ -40151,7 +40185,7 @@ class ResizableGridComponent {
40151
40185
  this.renderer.removeStyle(document.body, 'cursor');
40152
40186
  this.renderer.removeClass(document.body, 'no-select');
40153
40187
  requestAnimationFrame(() => {
40154
- this.checkAndApplyCollapse(this.colA.nativeElement.offsetWidth, this.colB.nativeElement.offsetWidth);
40188
+ this.checkAndApplyCollapse(this.getElementSize(this.colA.nativeElement), this.getElementSize(this.colB.nativeElement));
40155
40189
  });
40156
40190
  }
40157
40191
  }
@@ -40163,104 +40197,122 @@ class ResizableGridComponent {
40163
40197
  if (!this.colA || !this.colB) {
40164
40198
  return;
40165
40199
  }
40166
- const currentWidth = this.colA.nativeElement.offsetWidth;
40167
- const totalWidth = this.colA.nativeElement.parentElement?.offsetWidth || window.innerWidth;
40168
- let newWidthPx = currentWidth;
40200
+ const currentSize = this.getElementSize(this.colA.nativeElement);
40201
+ const totalSize = this.getTotalSize();
40202
+ let newSizePx = currentSize;
40169
40203
  // If the column is collapsed, always allow keyboard to restore it
40170
40204
  const colACollapsed = this.colA.nativeElement.classList.contains('collapsed');
40171
40205
  const colBCollapsed = this.colB.nativeElement.classList.contains('collapsed');
40206
+ const decreaseKey = this.isVertical ? 'ArrowUp' : 'ArrowLeft';
40207
+ const increaseKey = this.isVertical ? 'ArrowDown' : 'ArrowRight';
40172
40208
  switch (event.key) {
40173
- case 'ArrowLeft':
40209
+ case decreaseKey:
40174
40210
  if (colACollapsed) {
40175
- newWidthPx = this.collapseThreshold + this.resizeStep; // Restore to just above threshold
40211
+ newSizePx = this.collapseThreshold + this.resizeStep; // Restore to just above threshold
40176
40212
  }
40177
40213
  else {
40178
- newWidthPx = Math.max(0, currentWidth - this.resizeStep);
40214
+ newSizePx = Math.max(0, currentSize - this.resizeStep);
40179
40215
  }
40180
40216
  event.preventDefault();
40181
40217
  break;
40182
- case 'ArrowRight':
40218
+ case increaseKey:
40183
40219
  if (colACollapsed) {
40184
- newWidthPx = this.collapseThreshold + this.resizeStep;
40220
+ newSizePx = this.collapseThreshold + this.resizeStep;
40185
40221
  }
40186
40222
  else {
40187
- newWidthPx = Math.min(totalWidth, currentWidth + this.resizeStep);
40223
+ newSizePx = Math.min(totalSize, currentSize + this.resizeStep);
40188
40224
  }
40189
40225
  event.preventDefault();
40190
40226
  break;
40191
40227
  case 'Home':
40192
- newWidthPx = 0;
40228
+ newSizePx = 0;
40193
40229
  event.preventDefault();
40194
40230
  break;
40195
40231
  case 'End':
40196
- newWidthPx = totalWidth;
40232
+ newSizePx = totalSize;
40197
40233
  event.preventDefault();
40198
40234
  break;
40199
40235
  default:
40200
40236
  return;
40201
40237
  }
40202
- // If right column is collapsed, allow keyboard to restore it by expanding left
40203
- if (colBCollapsed && (event.key === 'ArrowRight' || event.key === 'End')) {
40204
- newWidthPx = totalWidth - this.collapseThreshold - this.resizeStep;
40238
+ // If right/bottom pane is collapsed, allow keyboard to restore it by expanding pane A
40239
+ if (colBCollapsed && (event.key === increaseKey || event.key === 'End')) {
40240
+ newSizePx = totalSize - this.collapseThreshold - this.resizeStep;
40205
40241
  }
40206
40242
  this.removeCollapseClasses();
40207
- this.updateColumnWidth(newWidthPx, true);
40243
+ this.updateColumnWidth(newSizePx, true);
40208
40244
  }
40209
40245
  /**
40210
- * Sets up the initial width of the left column, using localStorage if trackId is provided.
40246
+ * Sets up the initial size of pane A, using localStorage if trackId is provided.
40211
40247
  */
40212
40248
  setupInitialWidth() {
40213
40249
  if (!this.colA || !this.colB) {
40214
40250
  return;
40215
40251
  }
40216
- let initialWidth = this.leftColumnWidth;
40252
+ let initialSize = this.leftColumnWidth;
40217
40253
  // Only attempt to retrieve from localStorage if trackId is provided
40218
40254
  if (this.trackId) {
40219
- const savedWidth = localStorage.getItem(this.trackId);
40220
- if (savedWidth) {
40221
- initialWidth = savedWidth;
40255
+ const savedSize = localStorage.getItem(this.trackId);
40256
+ if (savedSize) {
40257
+ initialSize = savedSize;
40222
40258
  }
40223
40259
  }
40224
- this._colAWidth = initialWidth;
40225
- this.lastKnownNonCollapsedWidth = initialWidth;
40260
+ this._colAWidth = initialSize;
40261
+ this.lastKnownNonCollapsedWidth = initialSize;
40226
40262
  requestAnimationFrame(() => {
40227
- this.checkAndApplyCollapse(this.colA.nativeElement.offsetWidth, this.colB.nativeElement.offsetWidth);
40263
+ this.checkAndApplyCollapse(this.getElementSize(this.colA.nativeElement), this.getElementSize(this.colB.nativeElement));
40228
40264
  });
40229
40265
  }
40230
40266
  /**
40231
- * Updates the column A width and handles boundaries.
40232
- * @param targetWidthPx The desired width in pixels for column A.
40267
+ * Updates pane A's size and handles boundaries.
40268
+ * @param targetSizePx The desired size in pixels for pane A.
40233
40269
  * @param applyCollapseImmediately If true, calls checkAndApplyCollapse directly.
40234
40270
  */
40235
- updateColumnWidth(targetWidthPx, applyCollapseImmediately = false) {
40271
+ updateColumnWidth(targetSizePx, applyCollapseImmediately = false) {
40236
40272
  if (!this.colA || !this.colB) {
40237
40273
  return;
40238
40274
  }
40239
- const totalWidth = this.colA.nativeElement.parentElement?.offsetWidth || window.innerWidth;
40275
+ const totalSize = this.getTotalSize();
40240
40276
  // If not collapsible, enforce the threshold as the minimum
40241
- const minWidthPx = this.collapsible ? 0 : this.collapseThreshold;
40242
- const maxWidthPx = this.collapsible ? totalWidth : totalWidth - this.collapseThreshold;
40243
- let newWidthPx = Math.max(minWidthPx, targetWidthPx);
40244
- newWidthPx = Math.min(newWidthPx, maxWidthPx);
40245
- const newWidthString = `${newWidthPx}px`;
40246
- this._colAWidth = newWidthString;
40277
+ const minSizePx = this.collapsible ? 0 : this.collapseThreshold;
40278
+ const maxSizePx = this.collapsible ? totalSize : totalSize - this.collapseThreshold;
40279
+ let newSizePx = Math.max(minSizePx, targetSizePx);
40280
+ newSizePx = Math.min(newSizePx, maxSizePx);
40281
+ const newSizeString = `${newSizePx}px`;
40282
+ this._colAWidth = newSizeString;
40247
40283
  // Update lastKnownNonCollapsedWidth during drag, regardless of trackId
40248
- if (newWidthPx > 0 && newWidthPx < totalWidth) {
40249
- this.lastKnownNonCollapsedWidth = newWidthString;
40284
+ if (newSizePx > 0 && newSizePx < totalSize) {
40285
+ this.lastKnownNonCollapsedWidth = newSizeString;
40250
40286
  }
40251
40287
  // Only save to localStorage if trackId is provided and not in a collapsed state
40252
- if (this.trackId && newWidthPx > 0 && newWidthPx < totalWidth) {
40253
- localStorage.setItem(this.trackId, newWidthString);
40288
+ if (this.trackId && newSizePx > 0 && newSizePx < totalSize) {
40289
+ localStorage.setItem(this.trackId, newSizeString);
40254
40290
  }
40255
40291
  // A11y: If triggered by keyboard, apply collapse immediately for feedback
40256
40292
  if (applyCollapseImmediately) {
40257
- this.checkAndApplyCollapse(newWidthPx, totalWidth - newWidthPx);
40293
+ this.checkAndApplyCollapse(newSizePx, totalSize - newSizePx);
40258
40294
  }
40259
40295
  }
40260
40296
  /**
40261
- * Checks if either column should be collapsed based on their widths and applies the appropriate classes/styles.
40262
- * @param colAWidth Width of column A in pixels
40263
- * @param colBWidth Width of column B in pixels
40297
+ * Reads an element's size along the current resize axis (width for horizontal, height for vertical).
40298
+ */
40299
+ getElementSize(element) {
40300
+ return this.isVertical ? element.offsetHeight : element.offsetWidth;
40301
+ }
40302
+ /**
40303
+ * Total size of the grid along the current resize axis, falling back to the viewport size.
40304
+ */
40305
+ getTotalSize() {
40306
+ const parent = this.colA.nativeElement.parentElement;
40307
+ if (!parent) {
40308
+ return this.isVertical ? window.innerHeight : window.innerWidth;
40309
+ }
40310
+ return this.getElementSize(parent);
40311
+ }
40312
+ /**
40313
+ * Checks if either pane should be collapsed based on their sizes and applies the appropriate classes/styles.
40314
+ * @param colAWidth Size of pane A in pixels, along the resize axis
40315
+ * @param colBWidth Size of pane B in pixels, along the resize axis
40264
40316
  */
40265
40317
  checkAndApplyCollapse(colAWidth, colBWidth) {
40266
40318
  if (!this.colA || !this.colB) {
@@ -40321,11 +40373,11 @@ class ResizableGridComponent {
40321
40373
  this.renderer.removeClass(colBNative, 'expanded');
40322
40374
  }
40323
40375
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ResizableGridComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); }
40324
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", 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" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
40376
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: ResizableGridComponent, isStandalone: true, selector: "c8y-resizable-grid", inputs: { leftColumnWidth: "leftColumnWidth", trackId: "trackId", collapseThreshold: "collapseThreshold", collapsible: "collapsible", orientation: "orientation" }, host: { listeners: { "window:mousemove": "onMouseMove($event)", "window:mouseup": "onMouseUp()" }, properties: { "class.is-resizing": "this.isResizing", "style.--col-a-width": "this._colAWidth", "style.--col-a-height": "this._colAHeight" } }, viewQueries: [{ propertyName: "colA", first: true, predicate: ["colA"], descendants: true }, { propertyName: "colB", first: true, predicate: ["colB"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"resizable-grid-container\"\n [class.is-resizing]=\"isResizing\"\n [class.resizable-grid-container--vertical]=\"isVertical\"\n>\n <div\n class=\"col-a\"\n #colA\n [id]=\"colAId\"\n >\n <!-- Content for the left/top pane goes here -->\n <ng-content select=\"[left-pane]\"></ng-content>\n </div>\n <div\n class=\"resizer\"\n [attr.aria-label]=\"'Resize columns' | translate\"\n tabindex=\"0\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-orientation]=\"isVertical ? 'horizontal' : 'vertical'\"\n [attr.aria-controls]=\"colAId + ' ' + colBId\"\n [attr.aria-valuenow]=\"colAWidthPercent\"\n role=\"separator\"\n (mousedown)=\"onMouseDown($event)\"\n (keydown)=\"onKeyDown($event)\"\n >\n <i class=\"dlt-c8y-icon-arrow-circle-divide-horizontal\"></i>\n </div>\n <div\n class=\"col-b\"\n #colB\n [id]=\"colBId\"\n >\n <!-- Content for the right/bottom pane 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" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
40325
40377
  }
40326
40378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ResizableGridComponent, decorators: [{
40327
40379
  type: Component,
40328
- args: [{ selector: 'c8y-resizable-grid', standalone: true, imports: [CommonModule$1, C8yTranslatePipe], changeDetection: ChangeDetectionStrategy.Eager, 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" }]
40380
+ args: [{ selector: 'c8y-resizable-grid', standalone: true, imports: [CommonModule$1, C8yTranslatePipe], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n class=\"resizable-grid-container\"\n [class.is-resizing]=\"isResizing\"\n [class.resizable-grid-container--vertical]=\"isVertical\"\n>\n <div\n class=\"col-a\"\n #colA\n [id]=\"colAId\"\n >\n <!-- Content for the left/top pane goes here -->\n <ng-content select=\"[left-pane]\"></ng-content>\n </div>\n <div\n class=\"resizer\"\n [attr.aria-label]=\"'Resize columns' | translate\"\n tabindex=\"0\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-orientation]=\"isVertical ? 'horizontal' : 'vertical'\"\n [attr.aria-controls]=\"colAId + ' ' + colBId\"\n [attr.aria-valuenow]=\"colAWidthPercent\"\n role=\"separator\"\n (mousedown)=\"onMouseDown($event)\"\n (keydown)=\"onKeyDown($event)\"\n >\n <i class=\"dlt-c8y-icon-arrow-circle-divide-horizontal\"></i>\n </div>\n <div\n class=\"col-b\"\n #colB\n [id]=\"colBId\"\n >\n <!-- Content for the right/bottom pane goes here -->\n <ng-content select=\"[right-pane]\"></ng-content>\n </div>\n</div>\n" }]
40329
40381
  }], ctorParameters: () => [{ type: i0.Renderer2 }], propDecorators: { leftColumnWidth: [{
40330
40382
  type: Input
40331
40383
  }], trackId: [{
@@ -40334,6 +40386,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
40334
40386
  type: Input
40335
40387
  }], collapsible: [{
40336
40388
  type: Input
40389
+ }], orientation: [{
40390
+ type: Input
40337
40391
  }], colA: [{
40338
40392
  type: ViewChild,
40339
40393
  args: ['colA']
@@ -40346,6 +40400,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
40346
40400
  }], _colAWidth: [{
40347
40401
  type: HostBinding,
40348
40402
  args: ['style.--col-a-width']
40403
+ }], _colAHeight: [{
40404
+ type: HostBinding,
40405
+ args: ['style.--col-a-height']
40349
40406
  }], onMouseMove: [{
40350
40407
  type: HostListener,
40351
40408
  args: ['window:mousemove', ['$event']]
@@ -40904,7 +40961,8 @@ const DEFAULT_RESIZABLE_CONFIG = Object.freeze({
40904
40961
  collapseThreshold: 320,
40905
40962
  leftColumnWidth: '50%',
40906
40963
  trackId: 'c8y-sv-resizable-default',
40907
- collapsible: true
40964
+ collapsible: true,
40965
+ orientation: 'horizontal'
40908
40966
  });
40909
40967
  /**
40910
40968
  * A responsive split view layout component with automatic selection management and resizable panes.
@@ -40997,6 +41055,17 @@ const DEFAULT_RESIZABLE_CONFIG = Object.freeze({
40997
41055
  * </c8y-sv>
40998
41056
  * ```
40999
41057
  *
41058
+ * #### Vertical (top/bottom) split
41059
+ *
41060
+ * Set `orientation: 'vertical'` in `resizableConfig` to stack the list above the details pane,
41061
+ * with a draggable horizontal divider, instead of the default side-by-side layout.
41062
+ *
41063
+ * ```html
41064
+ * <c8y-sv [resizableConfig]="{ orientation: 'vertical', leftColumnWidth: '40%' }">
41065
+ * <!-- content -->
41066
+ * </c8y-sv>
41067
+ * ```
41068
+ *
41000
41069
  * #### List-Only mode
41001
41070
  *
41002
41071
  * Omit `<c8y-sv-details>` for a simple list view:
@@ -41015,10 +41084,11 @@ class SplitViewComponent {
41015
41084
  /**
41016
41085
  * Configuration for resizable grid behavior.
41017
41086
  *
41018
- * @property trackId - Unique ID for persisting column widths in localStorage
41019
- * @property leftColumnWidth - Initial width of left column (default: '50%')
41020
- * @property collapseThreshold - Width threshold (in px) for collapsing columns (default: 320)
41021
- * @property collapsible - Whether columns can collapse below threshold (default: true)
41087
+ * @property trackId - Unique ID for persisting pane sizes in localStorage
41088
+ * @property leftColumnWidth - Initial size of the first pane along the split axis (default: '50%')
41089
+ * @property collapseThreshold - Size threshold (in px) for collapsing panes (default: 320)
41090
+ * @property collapsible - Whether panes can collapse below threshold (default: true)
41091
+ * @property orientation - `'horizontal'` for left/right panes, `'vertical'` for top/bottom panes (default: 'horizontal')
41022
41092
  *
41023
41093
  * @example
41024
41094
  * ```html
@@ -41029,6 +41099,11 @@ class SplitViewComponent {
41029
41099
  * collapsible: false
41030
41100
  * }">
41031
41101
  * ```
41102
+ *
41103
+ * @example Vertical (top/bottom) split
41104
+ * ```html
41105
+ * <c8y-sv [resizableConfig]="{ orientation: 'vertical', leftColumnWidth: '40%' }">
41106
+ * ```
41032
41107
  */
41033
41108
  set resizableConfig(config) {
41034
41109
  this._resizableConfig = config ?? {};
@@ -41084,7 +41159,8 @@ class SplitViewComponent {
41084
41159
  collapseThreshold: DEFAULT_RESIZABLE_CONFIG.collapseThreshold,
41085
41160
  leftColumnWidth: DEFAULT_RESIZABLE_CONFIG.leftColumnWidth,
41086
41161
  trackId: DEFAULT_RESIZABLE_CONFIG.trackId,
41087
- collapsible: DEFAULT_RESIZABLE_CONFIG.collapsible
41162
+ collapsible: DEFAULT_RESIZABLE_CONFIG.collapsible,
41163
+ orientation: DEFAULT_RESIZABLE_CONFIG.orientation
41088
41164
  };
41089
41165
  this._checkViewportWidth();
41090
41166
  }
@@ -41172,20 +41248,28 @@ class SplitViewComponent {
41172
41248
  const leftColumnWidth = this._resizableConfig.leftColumnWidth ?? DEFAULT_RESIZABLE_CONFIG.leftColumnWidth;
41173
41249
  const trackId = this._resizableConfig.trackId ?? DEFAULT_RESIZABLE_CONFIG.trackId;
41174
41250
  const collapsible = this._resizableConfig.collapsible ?? DEFAULT_RESIZABLE_CONFIG.collapsible;
41251
+ const orientation = this._resizableConfig.orientation ?? DEFAULT_RESIZABLE_CONFIG.orientation;
41175
41252
  const current = this._memoizedResizableConfig;
41176
41253
  if (current.collapseThreshold !== collapseThreshold ||
41177
41254
  current.leftColumnWidth !== leftColumnWidth ||
41178
41255
  current.trackId !== trackId ||
41179
- current.collapsible !== collapsible) {
41180
- this._memoizedResizableConfig = { collapseThreshold, leftColumnWidth, trackId, collapsible };
41256
+ current.collapsible !== collapsible ||
41257
+ current.orientation !== orientation) {
41258
+ this._memoizedResizableConfig = {
41259
+ collapseThreshold,
41260
+ leftColumnWidth,
41261
+ trackId,
41262
+ collapsible,
41263
+ orientation
41264
+ };
41181
41265
  }
41182
41266
  }
41183
41267
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SplitViewComponent, deps: [{ token: SplitViewSelectionService }], target: i0.ɵɵFactoryTarget.Component }); }
41184
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", 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: i2$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$4.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" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
41268
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", 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 [orientation]=\"effectiveResizableConfig.orientation\"\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: i2$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$4.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", "orientation"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
41185
41269
  }
41186
41270
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SplitViewComponent, decorators: [{
41187
41271
  type: Component,
41188
- args: [{ selector: 'c8y-sv', standalone: true, imports: [CommonModule$1, RouterOutlet, C8yTranslatePipe, ResizableGridComponent], providers: [SplitViewSelectionService], changeDetection: ChangeDetectionStrategy.Eager, 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" }]
41272
+ args: [{ selector: 'c8y-sv', standalone: true, imports: [CommonModule$1, RouterOutlet, C8yTranslatePipe, ResizableGridComponent], providers: [SplitViewSelectionService], changeDetection: ChangeDetectionStrategy.Eager, 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 [orientation]=\"effectiveResizableConfig.orientation\"\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" }]
41189
41273
  }], ctorParameters: () => [{ type: SplitViewSelectionService }], propDecorators: { showDefaultRouterOutlet: [{
41190
41274
  type: Input
41191
41275
  }], isResizable: [{