@c8y/ngx-components 1024.20.1 → 1024.21.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.
Files changed (142) hide show
  1. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs +527 -12
  2. package/fesm2022/c8y-ngx-components-ai-agent-chat.mjs.map +1 -1
  3. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs +31 -9
  4. package/fesm2022/c8y-ngx-components-ai-ai-chat.mjs.map +1 -1
  5. package/fesm2022/c8y-ngx-components-ai.mjs +503 -62
  6. package/fesm2022/c8y-ngx-components-ai.mjs.map +1 -1
  7. package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs +2 -2
  8. package/fesm2022/c8y-ngx-components-alarm-event-selector.mjs.map +1 -1
  9. package/fesm2022/c8y-ngx-components-alarms.mjs +3 -3
  10. package/fesm2022/c8y-ngx-components-alarms.mjs.map +1 -1
  11. package/fesm2022/c8y-ngx-components-application-access-list.mjs +1 -1
  12. package/fesm2022/c8y-ngx-components-application-access-list.mjs.map +1 -1
  13. package/fesm2022/c8y-ngx-components-application-select.mjs +1 -1
  14. package/fesm2022/c8y-ngx-components-application-select.mjs.map +1 -1
  15. package/fesm2022/c8y-ngx-components-asset-properties.mjs +3 -2
  16. package/fesm2022/c8y-ngx-components-asset-properties.mjs.map +1 -1
  17. package/fesm2022/c8y-ngx-components-auth-configuration.mjs +1 -1
  18. package/fesm2022/c8y-ngx-components-auth-configuration.mjs.map +1 -1
  19. package/fesm2022/c8y-ngx-components-bookmarks.mjs +1 -1
  20. package/fesm2022/c8y-ngx-components-bookmarks.mjs.map +1 -1
  21. package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs +1 -1
  22. package/fesm2022/c8y-ngx-components-branding-shared-lazy.mjs.map +1 -1
  23. package/fesm2022/c8y-ngx-components-cockpit-config.mjs +5 -5
  24. package/fesm2022/c8y-ngx-components-cockpit-config.mjs.map +1 -1
  25. package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-version-history.component-Jyjkv4JT.mjs → c8y-ngx-components-context-dashboard-dashboard-version-history.component-CP1afwVe.mjs} +2 -2
  26. package/fesm2022/{c8y-ngx-components-context-dashboard-dashboard-version-history.component-Jyjkv4JT.mjs.map → c8y-ngx-components-context-dashboard-dashboard-version-history.component-CP1afwVe.mjs.map} +1 -1
  27. package/fesm2022/c8y-ngx-components-context-dashboard.mjs +81 -20
  28. package/fesm2022/c8y-ngx-components-context-dashboard.mjs.map +1 -1
  29. package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-UEUYsXBv.mjs → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-CRvgIgri.mjs} +2 -2
  30. package/fesm2022/{c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-UEUYsXBv.mjs.map → c8y-ngx-components-dashboard-details-advanced-tab-dashboard-details-advanced-tab.component-CRvgIgri.mjs.map} +1 -1
  31. package/fesm2022/c8y-ngx-components-dashboard-details-advanced-tab.mjs +2 -2
  32. package/fesm2022/c8y-ngx-components-dashboard-manager.mjs +1 -1
  33. package/fesm2022/c8y-ngx-components-dashboard-manager.mjs.map +1 -1
  34. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs +3 -3
  35. package/fesm2022/c8y-ngx-components-datapoint-explorer-view.mjs.map +1 -1
  36. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs +2 -2
  37. package/fesm2022/c8y-ngx-components-datapoint-selector.mjs.map +1 -1
  38. package/fesm2022/c8y-ngx-components-device-profile.mjs +2 -2
  39. package/fesm2022/c8y-ngx-components-device-profile.mjs.map +1 -1
  40. package/fesm2022/c8y-ngx-components-diagnostics.mjs +1 -1
  41. package/fesm2022/c8y-ngx-components-diagnostics.mjs.map +1 -1
  42. package/fesm2022/c8y-ngx-components-echart.mjs +146 -126
  43. package/fesm2022/c8y-ngx-components-echart.mjs.map +1 -1
  44. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs +2 -2
  45. package/fesm2022/c8y-ngx-components-ecosystem-application-plugins.mjs.map +1 -1
  46. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs +1 -1
  47. package/fesm2022/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
  48. package/fesm2022/c8y-ngx-components-ecosystem.mjs +4 -4
  49. package/fesm2022/c8y-ngx-components-ecosystem.mjs.map +1 -1
  50. package/fesm2022/c8y-ngx-components-events-events-timeline.mjs +1 -1
  51. package/fesm2022/c8y-ngx-components-events-events-timeline.mjs.map +1 -1
  52. package/fesm2022/c8y-ngx-components-events.mjs +2 -2
  53. package/fesm2022/c8y-ngx-components-events.mjs.map +1 -1
  54. package/fesm2022/c8y-ngx-components-icon-selector.mjs +4 -4
  55. package/fesm2022/c8y-ngx-components-icon-selector.mjs.map +1 -1
  56. package/fesm2022/c8y-ngx-components-operations-bulk-operation-list-item.mjs +1 -1
  57. package/fesm2022/c8y-ngx-components-operations-bulk-operation-list-item.mjs.map +1 -1
  58. package/fesm2022/c8y-ngx-components-operations-operations-list.mjs +1 -1
  59. package/fesm2022/c8y-ngx-components-operations-operations-list.mjs.map +1 -1
  60. package/fesm2022/c8y-ngx-components-operations-operations-timeline.mjs +1 -1
  61. package/fesm2022/c8y-ngx-components-operations-operations-timeline.mjs.map +1 -1
  62. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-configuration.mjs +1 -1
  63. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-configuration.mjs.map +1 -1
  64. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-device-profile.mjs +2 -2
  65. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-device-profile.mjs.map +1 -1
  66. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-firmware.mjs +2 -2
  67. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-firmware.mjs.map +1 -1
  68. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-software.mjs +2 -2
  69. package/fesm2022/c8y-ngx-components-operations-stepper-bulk-type-software.mjs.map +1 -1
  70. package/fesm2022/c8y-ngx-components-protocol-lpwan.mjs +5 -5
  71. package/fesm2022/c8y-ngx-components-protocol-lpwan.mjs.map +1 -1
  72. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs +1 -1
  73. package/fesm2022/c8y-ngx-components-protocol-opcua.mjs.map +1 -1
  74. package/fesm2022/c8y-ngx-components-register-device.mjs +3 -3
  75. package/fesm2022/c8y-ngx-components-register-device.mjs.map +1 -1
  76. package/fesm2022/c8y-ngx-components-remote-access-configurations.mjs +1 -1
  77. package/fesm2022/c8y-ngx-components-remote-access-configurations.mjs.map +1 -1
  78. package/fesm2022/c8y-ngx-components-replace-device-replace-device-wizard.mjs +1 -1
  79. package/fesm2022/c8y-ngx-components-replace-device-replace-device-wizard.mjs.map +1 -1
  80. package/fesm2022/c8y-ngx-components-report-dashboard.mjs +1 -1
  81. package/fesm2022/c8y-ngx-components-report-dashboard.mjs.map +1 -1
  82. package/fesm2022/c8y-ngx-components-repository-configuration.mjs +4 -4
  83. package/fesm2022/c8y-ngx-components-repository-configuration.mjs.map +1 -1
  84. package/fesm2022/c8y-ngx-components-repository-firmware.mjs +4 -4
  85. package/fesm2022/c8y-ngx-components-repository-firmware.mjs.map +1 -1
  86. package/fesm2022/c8y-ngx-components-repository-shared.mjs +2 -2
  87. package/fesm2022/c8y-ngx-components-repository-shared.mjs.map +1 -1
  88. package/fesm2022/c8y-ngx-components-repository-software.mjs +3 -3
  89. package/fesm2022/c8y-ngx-components-repository-software.mjs.map +1 -1
  90. package/fesm2022/c8y-ngx-components-static-assets-modal.mjs +1 -1
  91. package/fesm2022/c8y-ngx-components-static-assets-modal.mjs.map +1 -1
  92. package/fesm2022/c8y-ngx-components-tracking.mjs +1 -1
  93. package/fesm2022/c8y-ngx-components-tracking.mjs.map +1 -1
  94. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs +1 -1
  95. package/fesm2022/c8y-ngx-components-trusted-certificates.mjs.map +1 -1
  96. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs +17 -1
  97. package/fesm2022/c8y-ngx-components-widgets-definitions-html-widget.mjs.map +1 -1
  98. package/fesm2022/c8y-ngx-components-widgets-definitions-scada.mjs +21 -1
  99. package/fesm2022/c8y-ngx-components-widgets-definitions-scada.mjs.map +1 -1
  100. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs +60 -31
  101. package/fesm2022/c8y-ngx-components-widgets-implementations-asset-table.mjs.map +1 -1
  102. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs +2 -2
  103. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-graph.mjs.map +1 -1
  104. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs +2 -2
  105. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-list.mjs.map +1 -1
  106. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs +1 -1
  107. package/fesm2022/c8y-ngx-components-widgets-implementations-datapoints-table.mjs.map +1 -1
  108. package/fesm2022/c8y-ngx-components-widgets-implementations-image.mjs +1 -1
  109. package/fesm2022/c8y-ngx-components-widgets-implementations-image.mjs.map +1 -1
  110. package/fesm2022/c8y-ngx-components-widgets-implementations-quick-links.mjs +1 -1
  111. package/fesm2022/c8y-ngx-components-widgets-implementations-quick-links.mjs.map +1 -1
  112. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs +1 -1
  113. package/fesm2022/c8y-ngx-components-widgets-implementations-scada.mjs.map +1 -1
  114. package/fesm2022/c8y-ngx-components.mjs +500 -38
  115. package/fesm2022/c8y-ngx-components.mjs.map +1 -1
  116. package/locales/de.po +72 -0
  117. package/locales/es.po +72 -0
  118. package/locales/fr.po +72 -0
  119. package/locales/ja_JP.po +72 -0
  120. package/locales/ko.po +72 -0
  121. package/locales/locales.pot +72 -3
  122. package/locales/nl.po +72 -0
  123. package/locales/pl.po +73 -1
  124. package/locales/pt_BR.po +74 -2
  125. package/locales/zh_CN.po +72 -0
  126. package/locales/zh_TW.po +72 -0
  127. package/package.json +1 -1
  128. package/types/c8y-ngx-components-ai-agent-chat.d.ts +201 -3
  129. package/types/c8y-ngx-components-ai-agent-chat.d.ts.map +1 -1
  130. package/types/c8y-ngx-components-ai-ai-chat.d.ts +14 -4
  131. package/types/c8y-ngx-components-ai-ai-chat.d.ts.map +1 -1
  132. package/types/c8y-ngx-components-ai.d.ts +157 -2
  133. package/types/c8y-ngx-components-ai.d.ts.map +1 -1
  134. package/types/c8y-ngx-components-asset-properties.d.ts.map +1 -1
  135. package/types/c8y-ngx-components-context-dashboard.d.ts +37 -3
  136. package/types/c8y-ngx-components-context-dashboard.d.ts.map +1 -1
  137. package/types/c8y-ngx-components-echart.d.ts +6 -0
  138. package/types/c8y-ngx-components-echart.d.ts.map +1 -1
  139. package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts +5 -0
  140. package/types/c8y-ngx-components-widgets-implementations-asset-table.d.ts.map +1 -1
  141. package/types/c8y-ngx-components.d.ts +310 -12
  142. package/types/c8y-ngx-components.d.ts.map +1 -1
@@ -9573,6 +9573,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
9573
9573
  * - Traps Tab/Shift+Tab navigation within the dropdown menu
9574
9574
  * - Automatically closes dropdown and restores focus to toggle button when user selects an item with Enter/Space
9575
9575
  * - Prevents ESC key from propagating to parent elements (e.g., modals, drawers) and restores focus on close
9576
+ * - Keeps the dropdown open for items with `aria-haspopup="dialog"` (e.g. a delete button with a
9577
+ * `c8y-popover-confirm`), and suspends the trap so focus can move into that dialog
9578
+ * - Keeps the dropdown open for controls marked `data-dropdown-keep-open`, which act within the
9579
+ * menu instead of selecting something (e.g. "Load more" or clearing a search)
9576
9580
  * - Cleans up all listeners when the dropdown closes
9577
9581
  *
9578
9582
  * ## Usage
@@ -9613,7 +9617,13 @@ class DropdownFocusTrapDirective {
9613
9617
  return;
9614
9618
  }
9615
9619
  const target = event.target;
9616
- if (!this.dropdownMenuElement?.contains(target) || target.matches('input, textarea, select')) {
9620
+ if (!this.dropdownMenuElement?.contains(target) ||
9621
+ target.matches('input, textarea, select') ||
9622
+ target.closest('[data-dropdown-keep-open]')) {
9623
+ return;
9624
+ }
9625
+ if (this.opensDialog(target)) {
9626
+ this.suspendFocusTrap();
9617
9627
  return;
9618
9628
  }
9619
9629
  this.shouldRestoreFocus = true;
@@ -9623,11 +9633,27 @@ class DropdownFocusTrapDirective {
9623
9633
  if (event.key !== 'Escape') {
9624
9634
  return;
9625
9635
  }
9636
+ // While a dialog opened from the menu has focus, Escape belongs to that dialog.
9637
+ if (this.isFocusTrapSuspended() && !this.dropdownMenuElement?.contains(event.target)) {
9638
+ return;
9639
+ }
9626
9640
  event.preventDefault();
9627
9641
  event.stopImmediatePropagation();
9628
9642
  this.shouldRestoreFocus = true;
9629
9643
  this.dropdown.hide();
9630
9644
  };
9645
+ /** Mouse counterpart of the Enter/Space check in `handleSelection` for dialog triggers. */
9646
+ this.handleDialogTrigger = (event) => {
9647
+ if (this.opensDialog(event.target)) {
9648
+ this.suspendFocusTrap();
9649
+ }
9650
+ };
9651
+ /** Re-enables the trap once focus is back in the menu, for example after the dialog closed. */
9652
+ this.resumeFocusTrap = () => {
9653
+ if (this.focusTrap) {
9654
+ this.focusTrap.enabled = true;
9655
+ }
9656
+ };
9631
9657
  this.dropdown.onShown.pipe(takeUntilDestroyed()).subscribe(() => this.setupFocusTrap());
9632
9658
  this.dropdown.onHidden.pipe(takeUntilDestroyed()).subscribe(() => this.onDropdownHidden());
9633
9659
  }
@@ -9656,6 +9682,8 @@ class DropdownFocusTrapDirective {
9656
9682
  this.fitMenuToViewport();
9657
9683
  this.document.addEventListener('keydown', this.handleSelection, true);
9658
9684
  this.document.addEventListener('keydown', this.handleEscape, true);
9685
+ this.dropdownMenuElement.addEventListener('click', this.handleDialogTrigger, true);
9686
+ this.dropdownMenuElement.addEventListener('focusin', this.resumeFocusTrap);
9659
9687
  }, 0);
9660
9688
  }
9661
9689
  /**
@@ -9680,6 +9708,18 @@ class DropdownFocusTrapDirective {
9680
9708
  setTimeout(() => buttonToFocus.focus(), 0);
9681
9709
  }
9682
9710
  }
9711
+ opensDialog(target) {
9712
+ return !!target.closest('[aria-haspopup="dialog"]');
9713
+ }
9714
+ /** Lets focus leave the menu, as the dialog is appended outside of it. */
9715
+ suspendFocusTrap() {
9716
+ if (this.focusTrap) {
9717
+ this.focusTrap.enabled = false;
9718
+ }
9719
+ }
9720
+ isFocusTrapSuspended() {
9721
+ return !!this.focusTrap && !this.focusTrap.enabled;
9722
+ }
9683
9723
  /**
9684
9724
  * Cleans up the focus trap when the dropdown closes.
9685
9725
  * @private
@@ -9687,6 +9727,8 @@ class DropdownFocusTrapDirective {
9687
9727
  cleanupFocusTrap() {
9688
9728
  this.document.removeEventListener('keydown', this.handleSelection, true);
9689
9729
  this.document.removeEventListener('keydown', this.handleEscape, true);
9730
+ this.dropdownMenuElement?.removeEventListener('click', this.handleDialogTrigger, true);
9731
+ this.dropdownMenuElement?.removeEventListener('focusin', this.resumeFocusTrap);
9690
9732
  this.shouldRestoreFocus = false;
9691
9733
  if (this.focusTrap) {
9692
9734
  this.focusTrap.destroy();
@@ -16614,12 +16656,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
16614
16656
  type: Input
16615
16657
  }] } });
16616
16658
 
16659
+ let nextId = 0;
16660
+ /** How many frames to wait for the popover content to render before giving up on focusing it. */
16661
+ const MAX_FOCUS_FRAMES = 10;
16617
16662
  /**
16618
16663
  * A component to show a popover right next to the
16619
16664
  * user action. Add this component where the confirm modal
16620
16665
  * should be shown and toggle isOpen to display it. You
16621
16666
  * can use `await isShow()` to wait for a result on the
16622
16667
  * click action.
16668
+ *
16669
+ * When it opens, focus moves to its first button and Tab cycles through its buttons, Escape
16670
+ * cancels only the popover (not a modal or drawer around it), and focus returns to the element
16671
+ * that had it before (usually the trigger), so it can be used with the keyboard.
16623
16672
  */
16624
16673
  class PopoverConfirmComponent {
16625
16674
  constructor() {
@@ -16632,12 +16681,18 @@ class PopoverConfirmComponent {
16632
16681
  this.outsideClick = false;
16633
16682
  this.adaptivePosition = false;
16634
16683
  this.container = 'body';
16684
+ /**
16685
+ * Identifies the popover's footer in the DOM. ngx-bootstrap renders the popover outside this
16686
+ * component's view, so view queries cannot reach its buttons.
16687
+ */
16688
+ this.footerId = `c8y-popover-confirm-${nextId++}`;
16635
16689
  }
16636
16690
  /**
16637
16691
  * Show the popover. Wait until an action is performed on it.
16638
16692
  */
16639
16693
  async show(buttons) {
16640
16694
  this.buttons = buttons || this.buttons;
16695
+ const trigger = document.activeElement;
16641
16696
  this.isOpen = true;
16642
16697
  let result;
16643
16698
  try {
@@ -16651,24 +16706,62 @@ class PopoverConfirmComponent {
16651
16706
  }
16652
16707
  finally {
16653
16708
  this.isOpen = false;
16709
+ this.restoreFocus(trigger);
16654
16710
  }
16655
16711
  return result;
16656
16712
  }
16713
+ /** Moves focus into the popover once it is rendered. */
16714
+ focusFirstButton(framesLeft = MAX_FOCUS_FRAMES) {
16715
+ // `onShown` fires before ngx-bootstrap renders and positions the popover, and focus() is
16716
+ // ignored until it is visible, so retry frame by frame until focus lands.
16717
+ requestAnimationFrame(() => {
16718
+ const button = document.getElementById(this.footerId)?.querySelector('button');
16719
+ button?.focus();
16720
+ if (document.activeElement !== button && framesLeft > 1) {
16721
+ this.focusFirstButton(framesLeft - 1);
16722
+ }
16723
+ });
16724
+ }
16657
16725
  buttonStatus(status) {
16658
16726
  if (status) {
16659
16727
  return `btn-${status}`;
16660
16728
  }
16661
16729
  return 'btn-default';
16662
16730
  }
16731
+ /** Keeps Tab and Shift+Tab within the popover's buttons while it is open, as in a dialog. */
16732
+ cycleFocus(event) {
16733
+ const buttons = Array.from(document.getElementById(this.footerId)?.querySelectorAll('button') ?? []);
16734
+ const edge = event.shiftKey ? buttons[0] : buttons[buttons.length - 1];
16735
+ if (buttons.length && event.target === edge) {
16736
+ event.preventDefault();
16737
+ (event.shiftKey ? buttons[buttons.length - 1] : buttons[0]).focus();
16738
+ }
16739
+ }
16663
16740
  handleOutsideClick() {
16664
16741
  this.click(() => Promise.reject());
16665
16742
  }
16743
+ /**
16744
+ * Returns focus to the element that had it when the popover opened. Skipped when the user
16745
+ * already moved focus elsewhere, or when that element is gone (e.g. its list item was deleted).
16746
+ */
16747
+ restoreFocus(trigger) {
16748
+ setTimeout(() => {
16749
+ const active = document.activeElement;
16750
+ const focusIsLost = !active || active === document.body;
16751
+ if (trigger?.isConnected && (focusIsLost || this.isInPopover(active))) {
16752
+ trigger.focus();
16753
+ }
16754
+ });
16755
+ }
16756
+ isInPopover(element) {
16757
+ return !!document.getElementById(this.footerId)?.contains(element);
16758
+ }
16666
16759
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: PopoverConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
16667
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: PopoverConfirmComponent, isStandalone: true, selector: "c8y-popover-confirm", inputs: { buttons: "buttons", message: "message", title: "title", isOpen: "isOpen", containerClass: "containerClass", placement: "placement", outsideClick: "outsideClick", adaptivePosition: "adaptivePosition", container: "container" }, viewQueries: [{ propertyName: "popover", first: true, predicate: PopoverDirective, descendants: true }], ngImport: i0, template: "<div\n [class]=\"containerClass\"\n [popoverTitle]=\"title | translate\"\n [popover]=\"popover\"\n [isOpen]=\"isOpen\"\n [container]=\"container\"\n [placement]=\"placement\"\n [outsideClick]=\"outsideClick\"\n (onHidden)=\"handleOutsideClick()\"\n triggers=\"\"\n [adaptivePosition]=\"adaptivePosition\"\n>\n <ng-content></ng-content>\n</div>\n<ng-template #popover>\n <p>\n {{ message | translate }}\n </p>\n <div class=\"popover-footer d-flex gap-16 flex-wrap a-i-center\">\n <ng-container *ngFor=\"let button of buttons\">\n <button\n class=\"btn btn-sm m-l-0\"\n title=\"{{ button.label | translate }}\"\n [attr.data-cy]=\"'popover-confirm--' + (button.label | translate)\"\n [ngClass]=\"buttonStatus(button.status)\"\n (click)=\"click(button.action)\"\n >\n {{ button.label | translate }}\n </button>\n </ng-container>\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i1$8.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
16760
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: PopoverConfirmComponent, isStandalone: true, selector: "c8y-popover-confirm", inputs: { buttons: "buttons", message: "message", title: "title", isOpen: "isOpen", containerClass: "containerClass", placement: "placement", outsideClick: "outsideClick", adaptivePosition: "adaptivePosition", container: "container" }, viewQueries: [{ propertyName: "popover", first: true, predicate: PopoverDirective, descendants: true }], ngImport: i0, template: "<div\n [class]=\"containerClass\"\n [popoverTitle]=\"title | translate\"\n [popover]=\"popover\"\n triggers=\"\"\n [isOpen]=\"isOpen\"\n [container]=\"container\"\n [placement]=\"placement\"\n [outsideClick]=\"outsideClick\"\n (onHidden)=\"handleOutsideClick()\"\n (onShown)=\"focusFirstButton()\"\n [adaptivePosition]=\"adaptivePosition\"\n>\n <ng-content></ng-content>\n</div>\n<ng-template #popover>\n <!-- The popover is rendered outside its trigger (often in the body), so keep its clicks from\n reaching document listeners such as a dropdown's outside-click handler, which would close the\n menu that opened it. The buttons stop them too: a click on one closes the popover, removing this\n wrapper's listener before the event bubbles up to it. -->\n <div (click)=\"$event.stopPropagation()\">\n <p>\n {{ message | translate }}\n </p>\n <div\n class=\"popover-footer d-flex gap-16 flex-wrap a-i-center\"\n [id]=\"footerId\"\n (keydown.escape)=\"$event.stopPropagation(); handleOutsideClick()\"\n (keydown.tab)=\"cycleFocus($any($event))\"\n (keydown.shift.tab)=\"cycleFocus($any($event))\"\n >\n @for (button of buttons; track button) {\n <button\n class=\"btn btn-sm m-l-0\"\n title=\"{{ button.label | translate }}\"\n [attr.data-cy]=\"'popover-confirm--' + (button.label | translate)\"\n [ngClass]=\"buttonStatus(button.status)\"\n (click)=\"$event.stopPropagation(); click(button.action)\"\n >\n {{ button.label | translate }}\n </button>\n }\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i1$8.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
16668
16761
  }
16669
16762
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: PopoverConfirmComponent, decorators: [{
16670
16763
  type: Component,
16671
- args: [{ selector: 'c8y-popover-confirm', standalone: true, imports: [PopoverModule, NgFor, NgClass, C8yTranslatePipe], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n [class]=\"containerClass\"\n [popoverTitle]=\"title | translate\"\n [popover]=\"popover\"\n [isOpen]=\"isOpen\"\n [container]=\"container\"\n [placement]=\"placement\"\n [outsideClick]=\"outsideClick\"\n (onHidden)=\"handleOutsideClick()\"\n triggers=\"\"\n [adaptivePosition]=\"adaptivePosition\"\n>\n <ng-content></ng-content>\n</div>\n<ng-template #popover>\n <p>\n {{ message | translate }}\n </p>\n <div class=\"popover-footer d-flex gap-16 flex-wrap a-i-center\">\n <ng-container *ngFor=\"let button of buttons\">\n <button\n class=\"btn btn-sm m-l-0\"\n title=\"{{ button.label | translate }}\"\n [attr.data-cy]=\"'popover-confirm--' + (button.label | translate)\"\n [ngClass]=\"buttonStatus(button.status)\"\n (click)=\"click(button.action)\"\n >\n {{ button.label | translate }}\n </button>\n </ng-container>\n </div>\n</ng-template>\n" }]
16764
+ args: [{ selector: 'c8y-popover-confirm', standalone: true, imports: [PopoverModule, NgClass, C8yTranslatePipe], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n [class]=\"containerClass\"\n [popoverTitle]=\"title | translate\"\n [popover]=\"popover\"\n triggers=\"\"\n [isOpen]=\"isOpen\"\n [container]=\"container\"\n [placement]=\"placement\"\n [outsideClick]=\"outsideClick\"\n (onHidden)=\"handleOutsideClick()\"\n (onShown)=\"focusFirstButton()\"\n [adaptivePosition]=\"adaptivePosition\"\n>\n <ng-content></ng-content>\n</div>\n<ng-template #popover>\n <!-- The popover is rendered outside its trigger (often in the body), so keep its clicks from\n reaching document listeners such as a dropdown's outside-click handler, which would close the\n menu that opened it. The buttons stop them too: a click on one closes the popover, removing this\n wrapper's listener before the event bubbles up to it. -->\n <div (click)=\"$event.stopPropagation()\">\n <p>\n {{ message | translate }}\n </p>\n <div\n class=\"popover-footer d-flex gap-16 flex-wrap a-i-center\"\n [id]=\"footerId\"\n (keydown.escape)=\"$event.stopPropagation(); handleOutsideClick()\"\n (keydown.tab)=\"cycleFocus($any($event))\"\n (keydown.shift.tab)=\"cycleFocus($any($event))\"\n >\n @for (button of buttons; track button) {\n <button\n class=\"btn btn-sm m-l-0\"\n title=\"{{ button.label | translate }}\"\n [attr.data-cy]=\"'popover-confirm--' + (button.label | translate)\"\n [ngClass]=\"buttonStatus(button.status)\"\n (click)=\"$event.stopPropagation(); click(button.action)\"\n >\n {{ button.label | translate }}\n </button>\n }\n </div>\n </div>\n</ng-template>\n" }]
16672
16765
  }], propDecorators: { popover: [{
16673
16766
  type: ViewChild,
16674
16767
  args: [PopoverDirective, { static: false }]
@@ -17481,6 +17574,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17481
17574
  type: Input
17482
17575
  }] } });
17483
17576
 
17577
+ /**
17578
+ * A radio or checkbox that a list item can name and select on behalf of the row.
17579
+ *
17580
+ * The two find each other by injection rather than by `@ContentChild`: a control rendered from
17581
+ * another component's template is not content of the row, so a content query cannot see it, while
17582
+ * its element injector still resolves to the `c8y-li` that component sits in. Injection follows
17583
+ * the template in which an element is declared, so a control inside an `ng-template` created
17584
+ * elsewhere and inserted into the row would resolve to where that template was declared instead.
17585
+ */
17586
+ class ListItemSelectionControl {
17587
+ }
17588
+ /**
17589
+ * The part of a list item its projected radio or checkbox talks to. Provided by `c8y-li`.
17590
+ */
17591
+ class ListItemSelectionHost {
17592
+ }
17593
+
17484
17594
  /**
17485
17595
  * The footer can be used with either content projection
17486
17596
  * or a simple string as an input.
@@ -17503,6 +17613,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17503
17613
  type: Input
17504
17614
  }] } });
17505
17615
 
17616
+ /**
17617
+ * Content that handles a click itself. A row that selects on click leaves such content alone, the
17618
+ * way a native `<label>` does not forward clicks on the interactive content inside it.
17619
+ */
17620
+ const INTERACTIVE_CONTENT = 'a[href], button, input, select, textarea, label, details, [contenteditable], [role="button"], [role="link"]';
17506
17621
  /**
17507
17622
  * A list item is a representation of an item inside a list and
17508
17623
  * can be used to compose different styles in a list (mainly in a
@@ -17541,6 +17656,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17541
17656
  * ```
17542
17657
  */
17543
17658
  class ListItemComponent {
17659
+ static { this.instanceCount = 0; }
17544
17660
  /**
17545
17661
  * @ignore
17546
17662
  */
@@ -17583,6 +17699,13 @@ class ListItemComponent {
17583
17699
  * Indicates if the current list item is selectable.
17584
17700
  */
17585
17701
  this.selectable = true;
17702
+ /**
17703
+ * Lets a click anywhere on the item select its projected radio or checkbox, instead of only the
17704
+ * control itself. Off by default, as an item can carry its own click handling. A row click then no
17705
+ * longer toggles a `c8y-li-collapse` with `collapseWay="row"`; the item shows the collapse button
17706
+ * instead. Clicks on a button, link or other control inside the row are left to that element.
17707
+ */
17708
+ this.selectOnClick = false;
17586
17709
  /**
17587
17710
  * An event emitter which is triggered when the user collapses the content
17588
17711
  * via the chevron on the right.
@@ -17600,6 +17723,21 @@ class ListItemComponent {
17600
17723
  * @ignore
17601
17724
  */
17602
17725
  this.showCollapse = false;
17726
+ /**
17727
+ * Whether the item renders its own collapse button: when `collapseWay` is `button`, and when a
17728
+ * row click selects the control instead of toggling the collapse.
17729
+ * @ignore
17730
+ */
17731
+ this.showCollapseButton = false;
17732
+ /**
17733
+ * Whether a click on the row does something on its own: it toggles a `collapseWay="row"` collapse
17734
+ * or selects the control. The row then shows a pointer cursor. A click handler the author attaches
17735
+ * to the host is not visible here; add the `interact` class for that case.
17736
+ * @ignore
17737
+ */
17738
+ this.rowReactsToClick = false;
17739
+ /** In registration order; a row click selects the first. */
17740
+ this.selectionControls = [];
17603
17741
  this.pulse$ = new Subject();
17604
17742
  this.destroy$ = new Subject();
17605
17743
  this.ACTION_ITEM_HEIGHT = 40;
@@ -17612,6 +17750,26 @@ class ListItemComponent {
17612
17750
  .pipe(filter(apply => !!apply), tap(() => this.element.nativeElement.classList.remove('c8y-list--pulse')), delay(100), tap(() => this.element.nativeElement.classList.add('c8y-list--pulse')), takeUntil(this.destroy$))
17613
17751
  .subscribe();
17614
17752
  }
17753
+ /**
17754
+ * A radio or checkbox in this item carries no visible label of its own, so unless the author named
17755
+ * it, the row content names it. Called by the control, which may sit in another component's
17756
+ * template and therefore cannot be found with a content query.
17757
+ * @ignore
17758
+ */
17759
+ registerSelectionControl(control) {
17760
+ if (!this.selectionControls.includes(control)) {
17761
+ this.selectionControls.push(control);
17762
+ }
17763
+ if (!control.ariaLabel && !control.ariaLabelledBy) {
17764
+ control.ariaLabelledBy = this.ensureBodyId();
17765
+ }
17766
+ }
17767
+ /**
17768
+ * @ignore
17769
+ */
17770
+ unregisterSelectionControl(control) {
17771
+ this.selectionControls = this.selectionControls.filter(known => known !== control);
17772
+ }
17615
17773
  /**
17616
17774
  * @ignore
17617
17775
  */
@@ -17620,6 +17778,10 @@ class ListItemComponent {
17620
17778
  this.showFooter = this.itemFooter != null;
17621
17779
  this.showActions = this.itemActions.length > 0;
17622
17780
  this.showCollapse = this.itemCollapse != null;
17781
+ this.showCollapseButton =
17782
+ this.showCollapse && (this.itemCollapse.collapseWay === 'button' || this.selectOnClick);
17783
+ this.rowReactsToClick =
17784
+ this.selectOnClick || (this.showCollapse && this.itemCollapse.collapseWay === 'row');
17623
17785
  }
17624
17786
  /**
17625
17787
  * @ignore
@@ -17640,6 +17802,20 @@ class ListItemComponent {
17640
17802
  this.collapsed = !this.collapsed;
17641
17803
  this.collapsedChange.emit(this.collapsed);
17642
17804
  }
17805
+ /**
17806
+ * Handles a click on the item body. With `selectOnClick` set, the row acts as the label of its
17807
+ * radio or checkbox, so that selecting does not require hitting the control itself. Like a native
17808
+ * label, it leaves clicks on interactive content alone, and it leaves the collapse to its button.
17809
+ */
17810
+ rowClick(event) {
17811
+ if (!this.selectOnClick) {
17812
+ this.rowToggleCollapsed();
17813
+ return;
17814
+ }
17815
+ if (!this.clickedInteractiveContent(event)) {
17816
+ this.selectProjectedControl();
17817
+ }
17818
+ }
17643
17819
  /**
17644
17820
  * Toggles the collapse state in case the `collapseWay` is set to `row` and emits this state as
17645
17821
  * collapsedChange output as boolean.
@@ -17657,8 +17833,40 @@ class ListItemComponent {
17657
17833
  pulse() {
17658
17834
  this.pulse$.next(true);
17659
17835
  }
17836
+ /**
17837
+ * Whether the click landed on content that handles clicks itself: a button or link in the row, or
17838
+ * the control and its label, which the browser has already toggled, so that clicking it again
17839
+ * would undo the selection.
17840
+ */
17841
+ clickedInteractiveContent(event) {
17842
+ const target = event?.target;
17843
+ return target instanceof Element && target.closest(INTERACTIVE_CONTENT) !== null;
17844
+ }
17845
+ /** Clicks the first registered radio or checkbox, so that it selects and emits as it always does. */
17846
+ selectProjectedControl() {
17847
+ const control = this.selectionControls[0]?.input?.nativeElement;
17848
+ if (control && !control.disabled) {
17849
+ control.click();
17850
+ }
17851
+ }
17852
+ /**
17853
+ * Gives the item body an id the first time a control needs one. Set on the element rather than
17854
+ * bound in the template, so that items without a control keep their markup unchanged.
17855
+ */
17856
+ ensureBodyId() {
17857
+ if (!this.bodyId) {
17858
+ this.bodyId = `c8y-li-body-${ListItemComponent.instanceCount++}`;
17859
+ this.itemBody.nativeElement.id = this.bodyId;
17860
+ }
17861
+ return this.bodyId;
17862
+ }
17660
17863
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
17661
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ListItemComponent, isStandalone: true, selector: "c8y-list-item, c8y-li", inputs: { active: "active", highlighted: "highlighted", emptyActions: "emptyActions", dense: "dense", collapsed: "collapsed", selectable: "selectable" }, outputs: { collapsedChange: "collapsedChange" }, host: { properties: { "class.active": "this.active", "class.highlighted": "this.highlighted", "class.c8y-list__item--empty-actions": "this.emptyActions", "class.c8y-list__item--dense": "this.dense", "class.selectable": "this.selectable" }, classAttribute: "c8y-list__item" }, queries: [{ propertyName: "itemFooter", first: true, predicate: ListItemFooterComponent, descendants: true }, { propertyName: "itemCollapse", first: true, predicate: ListItemCollapseComponent, descendants: true }, { propertyName: "itemActions", predicate: ListItemActionComponent }], ngImport: i0, template: "<div\n [ngClass]=\"{ expanded: !collapsed, interact: itemCollapse && itemCollapse.collapseWay === 'row' }\"\n>\n <div class=\"c8y-list__item__block\">\n <ng-content select=\"c8y-list-item-drag-handle, c8y-li-drag-handle\"></ng-content>\n <ng-content select=\"c8y-list-item-radio, c8y-li-radio\"></ng-content>\n <ng-content select=\"c8y-list-item-checkbox, c8y-li-checkbox\"></ng-content>\n\n <ng-content select=\"c8y-list-item-icon, c8y-li-icon\"></ng-content>\n\n <div\n class=\"c8y-list__item__body text-truncate-wrap\"\n (click)=\"rowToggleCollapsed()\"\n >\n <ng-content select=\"c8y-list-item-body, c8y-li-body\"></ng-content>\n <ng-content></ng-content>\n\n @if (showFooter) {\n <div class=\"c8y-list__item__footer\">\n <ng-content select=\"c8y-list-item-footer, c8y-li-footer\"></ng-content>\n </div>\n }\n </div>\n\n @if ((showCollapse && itemCollapse && itemCollapse.collapseWay === 'button') || showActions) {\n <div class=\"c8y-list__item__actions\">\n @if (showCollapse && itemCollapse.collapseWay === 'button') {\n <button\n class=\"collapse-btn\"\n title=\"{{ 'Expand' | translate }}\"\n [attr.aria-expanded]=\"!collapsed\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n data-cy=\"c8y-li--collapse-btn\"\n >\n <i [c8yIcon]=\"'chevron-down'\"></i>\n </button>\n }\n\n @if (showActions) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n #liDropdownActions=\"bs-dropdown\"\n dropdown\n #dropDirection=\"bs-dropdown\"\n c8yDropdownFocusTrap\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n type=\"button\"\n dropdownToggle\n data-cy=\"c8y-li--actions-btn\"\n >\n <i [c8yIcon]=\"'ellipsis-v'\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n data-cy=\"list-item--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n\n @for (action of actions; track action) {\n <ng-container *ngTemplateOutlet=\"action.template\"></ng-container>\n }\n </ul>\n </div>\n\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n }\n </div>\n }\n </div>\n\n @if (showCollapse) {\n <div\n [collapse]=\"collapsed\"\n [isAnimated]=\"true\"\n >\n <div class=\"c8y-list__item__collapse--container\">\n <ng-content select=\"c8y-list-item-collapse, c8y-li-collapse\"></ng-content>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: DropdownFocusTrapDirective, selector: "[c8yDropdownFocusTrap]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "directive", type: i2$3.CollapseDirective, selector: "[collapse]", inputs: ["display", "isAnimated", "collapse"], outputs: ["collapsed", "collapses", "expanded", "expands"], exportAs: ["bs-collapse"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
17864
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: ListItemComponent, isStandalone: true, selector: "c8y-list-item, c8y-li", inputs: { active: "active", highlighted: "highlighted", emptyActions: "emptyActions", dense: "dense", collapsed: "collapsed", selectable: "selectable", selectOnClick: ["selectOnClick", "selectOnClick", booleanAttribute] }, outputs: { collapsedChange: "collapsedChange" }, host: { properties: { "class.active": "this.active", "class.highlighted": "this.highlighted", "class.c8y-list__item--empty-actions": "this.emptyActions", "class.c8y-list__item--dense": "this.dense", "class.selectable": "this.selectable" }, classAttribute: "c8y-list__item" }, providers: [
17865
+ {
17866
+ provide: ListItemSelectionHost,
17867
+ useExisting: forwardRef(() => ListItemComponent)
17868
+ }
17869
+ ], queries: [{ propertyName: "itemFooter", first: true, predicate: ListItemFooterComponent, descendants: true }, { propertyName: "itemCollapse", first: true, predicate: ListItemCollapseComponent, descendants: true }, { propertyName: "itemActions", predicate: ListItemActionComponent }], viewQueries: [{ propertyName: "itemBody", first: true, predicate: ["itemBody"], descendants: true, static: true }], ngImport: i0, template: "<div [ngClass]=\"{ expanded: !collapsed, interact: rowReactsToClick }\">\n <div class=\"c8y-list__item__block\">\n <ng-content select=\"c8y-list-item-drag-handle, c8y-li-drag-handle\"></ng-content>\n <ng-content select=\"c8y-list-item-radio, c8y-li-radio\"></ng-content>\n <ng-content select=\"c8y-list-item-checkbox, c8y-li-checkbox\"></ng-content>\n\n <ng-content select=\"c8y-list-item-icon, c8y-li-icon\"></ng-content>\n\n <div\n class=\"c8y-list__item__body text-truncate-wrap\"\n #itemBody\n (click)=\"rowClick($event)\"\n >\n <ng-content select=\"c8y-list-item-body, c8y-li-body\"></ng-content>\n <ng-content></ng-content>\n\n @if (showFooter) {\n <div class=\"c8y-list__item__footer\">\n <ng-content select=\"c8y-list-item-footer, c8y-li-footer\"></ng-content>\n </div>\n }\n </div>\n\n @if (showCollapseButton || showActions) {\n <div class=\"c8y-list__item__actions\">\n @if (showCollapseButton) {\n <button\n class=\"collapse-btn\"\n title=\"{{ 'Expand' | translate }}\"\n [attr.aria-expanded]=\"!collapsed\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n data-cy=\"c8y-li--collapse-btn\"\n >\n <i [c8yIcon]=\"'chevron-down'\"></i>\n </button>\n }\n\n @if (showActions) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n #liDropdownActions=\"bs-dropdown\"\n dropdown\n #dropDirection=\"bs-dropdown\"\n c8yDropdownFocusTrap\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n type=\"button\"\n dropdownToggle\n data-cy=\"c8y-li--actions-btn\"\n >\n <i [c8yIcon]=\"'ellipsis-v'\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n data-cy=\"list-item--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n\n @for (action of actions; track action) {\n <ng-container *ngTemplateOutlet=\"action.template\"></ng-container>\n }\n </ul>\n </div>\n\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n }\n </div>\n }\n </div>\n\n @if (showCollapse) {\n <div\n [collapse]=\"collapsed\"\n [isAnimated]=\"true\"\n >\n <div class=\"c8y-list__item__collapse--container\">\n <ng-content select=\"c8y-list-item-collapse, c8y-li-collapse\"></ng-content>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: DropdownFocusTrapDirective, selector: "[c8yDropdownFocusTrap]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: CollapseModule }, { kind: "directive", type: i2$3.CollapseDirective, selector: "[collapse]", inputs: ["display", "isAnimated", "collapse"], outputs: ["collapsed", "collapses", "expanded", "expands"], exportAs: ["bs-collapse"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
17662
17870
  }
17663
17871
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemComponent, decorators: [{
17664
17872
  type: Component,
@@ -17674,7 +17882,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17674
17882
  NgTemplateOutlet,
17675
17883
  CollapseModule,
17676
17884
  C8yTranslatePipe
17677
- ], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n [ngClass]=\"{ expanded: !collapsed, interact: itemCollapse && itemCollapse.collapseWay === 'row' }\"\n>\n <div class=\"c8y-list__item__block\">\n <ng-content select=\"c8y-list-item-drag-handle, c8y-li-drag-handle\"></ng-content>\n <ng-content select=\"c8y-list-item-radio, c8y-li-radio\"></ng-content>\n <ng-content select=\"c8y-list-item-checkbox, c8y-li-checkbox\"></ng-content>\n\n <ng-content select=\"c8y-list-item-icon, c8y-li-icon\"></ng-content>\n\n <div\n class=\"c8y-list__item__body text-truncate-wrap\"\n (click)=\"rowToggleCollapsed()\"\n >\n <ng-content select=\"c8y-list-item-body, c8y-li-body\"></ng-content>\n <ng-content></ng-content>\n\n @if (showFooter) {\n <div class=\"c8y-list__item__footer\">\n <ng-content select=\"c8y-list-item-footer, c8y-li-footer\"></ng-content>\n </div>\n }\n </div>\n\n @if ((showCollapse && itemCollapse && itemCollapse.collapseWay === 'button') || showActions) {\n <div class=\"c8y-list__item__actions\">\n @if (showCollapse && itemCollapse.collapseWay === 'button') {\n <button\n class=\"collapse-btn\"\n title=\"{{ 'Expand' | translate }}\"\n [attr.aria-expanded]=\"!collapsed\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n data-cy=\"c8y-li--collapse-btn\"\n >\n <i [c8yIcon]=\"'chevron-down'\"></i>\n </button>\n }\n\n @if (showActions) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n #liDropdownActions=\"bs-dropdown\"\n dropdown\n #dropDirection=\"bs-dropdown\"\n c8yDropdownFocusTrap\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n type=\"button\"\n dropdownToggle\n data-cy=\"c8y-li--actions-btn\"\n >\n <i [c8yIcon]=\"'ellipsis-v'\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n data-cy=\"list-item--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n\n @for (action of actions; track action) {\n <ng-container *ngTemplateOutlet=\"action.template\"></ng-container>\n }\n </ul>\n </div>\n\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n }\n </div>\n }\n </div>\n\n @if (showCollapse) {\n <div\n [collapse]=\"collapsed\"\n [isAnimated]=\"true\"\n >\n <div class=\"c8y-list__item__collapse--container\">\n <ng-content select=\"c8y-list-item-collapse, c8y-li-collapse\"></ng-content>\n </div>\n </div>\n }\n</div>\n" }]
17885
+ ], providers: [
17886
+ {
17887
+ provide: ListItemSelectionHost,
17888
+ useExisting: forwardRef(() => ListItemComponent)
17889
+ }
17890
+ ], changeDetection: ChangeDetectionStrategy.Eager, template: "<div [ngClass]=\"{ expanded: !collapsed, interact: rowReactsToClick }\">\n <div class=\"c8y-list__item__block\">\n <ng-content select=\"c8y-list-item-drag-handle, c8y-li-drag-handle\"></ng-content>\n <ng-content select=\"c8y-list-item-radio, c8y-li-radio\"></ng-content>\n <ng-content select=\"c8y-list-item-checkbox, c8y-li-checkbox\"></ng-content>\n\n <ng-content select=\"c8y-list-item-icon, c8y-li-icon\"></ng-content>\n\n <div\n class=\"c8y-list__item__body text-truncate-wrap\"\n #itemBody\n (click)=\"rowClick($event)\"\n >\n <ng-content select=\"c8y-list-item-body, c8y-li-body\"></ng-content>\n <ng-content></ng-content>\n\n @if (showFooter) {\n <div class=\"c8y-list__item__footer\">\n <ng-content select=\"c8y-list-item-footer, c8y-li-footer\"></ng-content>\n </div>\n }\n </div>\n\n @if (showCollapseButton || showActions) {\n <div class=\"c8y-list__item__actions\">\n @if (showCollapseButton) {\n <button\n class=\"collapse-btn\"\n title=\"{{ 'Expand' | translate }}\"\n [attr.aria-expanded]=\"!collapsed\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n data-cy=\"c8y-li--collapse-btn\"\n >\n <i [c8yIcon]=\"'chevron-down'\"></i>\n </button>\n }\n\n @if (showActions) {\n <div\n class=\"dropdown\"\n placement=\"bottom right\"\n container=\"body\"\n #liDropdownActions=\"bs-dropdown\"\n dropdown\n #dropDirection=\"bs-dropdown\"\n c8yDropdownFocusTrap\n >\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n title=\"{{ 'Actions' | translate }}\"\n type=\"button\"\n dropdownToggle\n data-cy=\"c8y-li--actions-btn\"\n >\n <i [c8yIcon]=\"'ellipsis-v'\"></i>\n </button>\n <ul\n class=\"dropdown-menu dropdown-menu-right\"\n data-cy=\"list-item--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n\n @for (action of actions; track action) {\n <ng-container *ngTemplateOutlet=\"action.template\"></ng-container>\n }\n </ul>\n </div>\n\n <ng-content select=\"c8y-list-item-action, c8y-li-action\"></ng-content>\n }\n </div>\n }\n </div>\n\n @if (showCollapse) {\n <div\n [collapse]=\"collapsed\"\n [isAnimated]=\"true\"\n >\n <div class=\"c8y-list__item__collapse--container\">\n <ng-content select=\"c8y-list-item-collapse, c8y-li-collapse\"></ng-content>\n </div>\n </div>\n }\n</div>\n" }]
17678
17891
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { active: [{
17679
17892
  type: Input
17680
17893
  }, {
@@ -17702,6 +17915,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17702
17915
  }, {
17703
17916
  type: HostBinding,
17704
17917
  args: ['class.selectable']
17918
+ }], selectOnClick: [{
17919
+ type: Input,
17920
+ args: [{ transform: booleanAttribute }]
17705
17921
  }], collapsedChange: [{
17706
17922
  type: Output
17707
17923
  }], itemFooter: [{
@@ -17713,6 +17929,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
17713
17929
  }], itemCollapse: [{
17714
17930
  type: ContentChild,
17715
17931
  args: [ListItemCollapseComponent, { static: false }]
17932
+ }], itemBody: [{
17933
+ type: ViewChild,
17934
+ args: ['itemBody', { static: true }]
17716
17935
  }] } });
17717
17936
 
17718
17937
  /**
@@ -17903,7 +18122,7 @@ class SelectKeyboardService {
17903
18122
  return this.handleArrowKeySelection(event, input, items, dropdown);
17904
18123
  }
17905
18124
  if (event.code === this.KEYCODE_ESC) {
17906
- return this.handleCancel(event, dropdown, input);
18125
+ return this.handleCancel(event, dropdown);
17907
18126
  }
17908
18127
  if (this.options.keyboardSearch) {
17909
18128
  return this.handleInputBoxSearch(items, input);
@@ -17943,13 +18162,18 @@ class SelectKeyboardService {
17943
18162
  if (this.options.emptyInput) {
17944
18163
  input.value = '';
17945
18164
  }
18165
+ // Enter and Tab pick the highlighted item and close the menu. Focus stays on
18166
+ // the input, like a native select: Enter keeps it there, Tab moves it on to
18167
+ // the next control because its default is not prevented.
17946
18168
  if (keyCode === this.KEYCODE_ENTER || keyCode === this.KEYCODE_TAB) {
17947
- if (index > -1) {
17948
- event.preventDefault();
18169
+ // Only an open menu offers a choice; a stale highlight must not be picked from a closed one.
18170
+ if (index > -1 && dropdown.isOpen) {
18171
+ if (keyCode === this.KEYCODE_ENTER) {
18172
+ event.preventDefault();
18173
+ }
17949
18174
  items[index].element.nativeElement.click();
17950
18175
  }
17951
18176
  dropdown.hide();
17952
- input.blur();
17953
18177
  return index;
17954
18178
  }
17955
18179
  if (keyCode === this.KEYCODE_SPACE) {
@@ -17963,18 +18187,30 @@ class SelectKeyboardService {
17963
18187
  return index;
17964
18188
  }
17965
18189
  const upOrDown = keyCode === this.KEYCODE_DOWN ? 1 : -1;
18190
+ // The arrow keys are the expected way to open a closed dropdown from its input.
18191
+ if (!dropdown.isOpen) {
18192
+ event.preventDefault();
18193
+ dropdown.show();
18194
+ }
17966
18195
  if (index > -1) {
17967
18196
  items[index].highlighted = false;
17968
18197
  }
17969
18198
  return this.selectNextItemOnKeyboardMove(items, index, upOrDown);
17970
18199
  }
17971
- handleCancel(event, dropdown, input) {
18200
+ /**
18201
+ * Escape closes the menu and keeps focus on the input. Propagation stops so
18202
+ * a modal hosting the dropdown does not close with it.
18203
+ */
18204
+ handleCancel(event, dropdown) {
17972
18205
  event.stopPropagation();
17973
18206
  dropdown.hide();
17974
- input.blur();
17975
18207
  return -1;
17976
18208
  }
17977
18209
  selectNextItemOnKeyboardMove(items, index, upOrDown) {
18210
+ // Opening with an arrow key happens before the menu items exist; nothing to highlight yet.
18211
+ if (items.length === 0) {
18212
+ return -1;
18213
+ }
17978
18214
  if (items[index + upOrDown]) {
17979
18215
  if (!items[index + upOrDown].selectable) {
17980
18216
  return this.selectNextItemOnKeyboardMove(items, index + upOrDown, upOrDown);
@@ -18003,6 +18239,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
18003
18239
  type: Injectable
18004
18240
  }] });
18005
18241
 
18242
+ let nextUniqueId$1 = 0;
18006
18243
  class TypeaheadComponent {
18007
18244
  constructor(selectKeyboardService) {
18008
18245
  this.selectKeyboardService = selectKeyboardService;
@@ -18022,6 +18259,17 @@ class TypeaheadComponent {
18022
18259
  this.highlightFirstItem = true;
18023
18260
  this.onSearch = new EventEmitter();
18024
18261
  this.onIconClick = new EventEmitter();
18262
+ /**
18263
+ * Id of the dropdown popup. The toggle button references it via `aria-controls`.
18264
+ * @ignore
18265
+ */
18266
+ this.popupId = `c8y-typeahead-popup-${nextUniqueId$1++}`;
18267
+ /**
18268
+ * Set by a click inside the menu. Clicking a list item drops focus to the
18269
+ * body (or to a hosting modal) because the item is not focusable and the menu
18270
+ * is removed on close, so `onHidden` brings focus back to the input.
18271
+ */
18272
+ this.restoreFocusOnHide = false;
18025
18273
  this.destroyed$ = new Subject();
18026
18274
  }
18027
18275
  writeValue(value) {
@@ -18053,8 +18301,41 @@ class TypeaheadComponent {
18053
18301
  return get(this.selected, this.displayProperty, '');
18054
18302
  }
18055
18303
  onShown() {
18304
+ this.restoreFocusOnHide = false;
18305
+ this.focus();
18306
+ }
18307
+ onHidden() {
18308
+ if (this.restoreFocusOnHide) {
18309
+ this.restoreFocusOnHide = false;
18310
+ this.focus();
18311
+ }
18312
+ }
18313
+ /**
18314
+ * Remembers that the menu was clicked, so focus can be restored once the
18315
+ * click has closed the dropdown.
18316
+ * @ignore
18317
+ */
18318
+ onMenuClick() {
18319
+ this.restoreFocusOnHide = true;
18320
+ }
18321
+ /**
18322
+ * Moves focus to the search input. Focusing does not open the dropdown; use `open()` for that.
18323
+ */
18324
+ focus() {
18056
18325
  this.searchControl.nativeElement.focus();
18057
18326
  }
18327
+ /**
18328
+ * Opens the dropdown.
18329
+ */
18330
+ open() {
18331
+ this.dropdown.show();
18332
+ }
18333
+ /**
18334
+ * Closes the dropdown.
18335
+ */
18336
+ close() {
18337
+ this.dropdown.hide();
18338
+ }
18058
18339
  /**
18059
18340
  * Resets the input field - clear value and clean field to be pristine and untouched.
18060
18341
  */
@@ -18107,7 +18388,7 @@ class TypeaheadComponent {
18107
18388
  return null;
18108
18389
  }
18109
18390
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TypeaheadComponent, deps: [{ token: SelectKeyboardService }], target: i0.ɵɵFactoryTarget.Component }); }
18110
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: TypeaheadComponent, isStandalone: true, selector: "c8y-typeahead", inputs: { required: "required", maxlength: "maxlength", disabled: "disabled", allowFreeEntries: "allowFreeEntries", placeholder: "placeholder", displayProperty: "displayProperty", icon: "icon", name: "name", autoClose: "autoClose", hideNew: "hideNew", container: "container", selected: "selected", title: "title", highlightFirstItem: "highlightFirstItem" }, outputs: { onSearch: "onSearch", onIconClick: "onIconClick" }, providers: [
18391
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: TypeaheadComponent, isStandalone: true, selector: "c8y-typeahead", inputs: { required: "required", maxlength: "maxlength", disabled: "disabled", allowFreeEntries: "allowFreeEntries", placeholder: "placeholder", displayProperty: "displayProperty", icon: "icon", name: "name", autoClose: "autoClose", hideNew: "hideNew", container: "container", selected: "selected", title: "title", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", highlightFirstItem: "highlightFirstItem" }, outputs: { onSearch: "onSearch", onIconClick: "onIconClick" }, providers: [
18111
18392
  {
18112
18393
  provide: NG_VALUE_ACCESSOR,
18113
18394
  multi: true,
@@ -18119,7 +18400,7 @@ class TypeaheadComponent {
18119
18400
  multi: true
18120
18401
  },
18121
18402
  SelectKeyboardService
18122
- ], queries: [{ propertyName: "list", predicate: ListItemComponent }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "searchControlModel", first: true, predicate: ["searchControlModel"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }], ngImport: i0, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"true\"\n (onShown)=\"onShown()\"\n [isDisabled]=\"disabled\"\n dropdownToggle\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n #searchControl\n #searchControlModel=\"ngModel\"\n [ngClass]=\"{\n 'p-r-80':\n !hideNew &&\n (selected\n ? selected.id === null && getDisplayProperty()?.length > 0 && allowFreeEntries\n : false),\n 'p-r-40': hideNew || getDisplayProperty()?.length === 0\n }\"\n [required]=\"required\"\n [ngModel]=\"selected ? getDisplayProperty() : ''\"\n [placeholder]=\"placeholder | translate\"\n (blur)=\"doBlur()\"\n [name]=\"name\"\n [maxlength]=\"maxlength\"\n [disabled]=\"disabled\"\n />\n @if (\n !hideNew &&\n selected &&\n selected.id === null &&\n getDisplayProperty()?.length > 0 &&\n allowFreeEntries\n ) {\n <span\n class=\"label label-info p-absolute\"\n style=\"top: 10px; right: 40px; z-index: 10\"\n >\n {{ 'New' | translate }}\n </span>\n }\n\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n [title]=\"title\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"typeahead-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal\"\n [style.width]=\"container === 'body' ? searchControl.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"typeahead--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"div, c8y-li, c8y-list-item, button, a\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$7.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
18403
+ ], queries: [{ propertyName: "list", predicate: ListItemComponent }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "searchControlModel", first: true, predicate: ["searchControlModel"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }], ngImport: i0, template: "@let placeholderText = placeholder ? (placeholder | translate) : null;\n@let fallbackLabel = placeholderText ? placeholderText : (title | translate);\n@let inputLabel = ariaLabelledby ? null : ariaLabel ? ariaLabel : fallbackLabel;\n\n<!-- role=\"group\" legalizes the aria dropdownToggle sets here; the button below carries the state. -->\n<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n role=\"group\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n [isDisabled]=\"disabled\"\n dropdownToggle\n>\n <div class=\"input-group input-group-dropdown\">\n <input\n class=\"form-control text-truncate\"\n [attr.aria-label]=\"inputLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n type=\"text\"\n #searchControl\n #searchControlModel=\"ngModel\"\n [ngClass]=\"{\n 'p-r-80':\n !hideNew &&\n (selected\n ? selected.id === null && getDisplayProperty()?.length > 0 && allowFreeEntries\n : false),\n 'p-r-40': hideNew || getDisplayProperty()?.length === 0\n }\"\n [required]=\"required\"\n [ngModel]=\"selected ? getDisplayProperty() : ''\"\n [attr.placeholder]=\"placeholderText\"\n (blur)=\"doBlur()\"\n [name]=\"name\"\n [maxlength]=\"maxlength\"\n [disabled]=\"disabled\"\n />\n @if (\n !hideNew &&\n selected &&\n selected.id === null &&\n getDisplayProperty()?.length > 0 &&\n allowFreeEntries\n ) {\n <span\n class=\"label label-info p-absolute\"\n style=\"top: 10px; right: 40px; z-index: 10\"\n >\n {{ 'New' | translate }}\n </span>\n }\n\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n [title]=\"title\"\n [attr.aria-expanded]=\"dropdown.isOpen\"\n [attr.aria-controls]=\"popupId\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"typeahead-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal\"\n [style.width]=\"container === 'body' ? searchControl.clientWidth + 'px' : undefined\"\n [id]=\"popupId\"\n data-cy=\"typeahead--dropdown-menu\"\n (click)=\"onMenuClick()\"\n *dropdownMenu\n >\n <ng-content select=\"div, c8y-li, c8y-list-item, button, a\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$7.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
18123
18404
  }
18124
18405
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TypeaheadComponent, decorators: [{
18125
18406
  type: Component,
@@ -18143,7 +18424,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
18143
18424
  IconDirective,
18144
18425
  ListGroupComponent,
18145
18426
  C8yTranslatePipe
18146
- ], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"true\"\n (onShown)=\"onShown()\"\n [isDisabled]=\"disabled\"\n dropdownToggle\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n #searchControl\n #searchControlModel=\"ngModel\"\n [ngClass]=\"{\n 'p-r-80':\n !hideNew &&\n (selected\n ? selected.id === null && getDisplayProperty()?.length > 0 && allowFreeEntries\n : false),\n 'p-r-40': hideNew || getDisplayProperty()?.length === 0\n }\"\n [required]=\"required\"\n [ngModel]=\"selected ? getDisplayProperty() : ''\"\n [placeholder]=\"placeholder | translate\"\n (blur)=\"doBlur()\"\n [name]=\"name\"\n [maxlength]=\"maxlength\"\n [disabled]=\"disabled\"\n />\n @if (\n !hideNew &&\n selected &&\n selected.id === null &&\n getDisplayProperty()?.length > 0 &&\n allowFreeEntries\n ) {\n <span\n class=\"label label-info p-absolute\"\n style=\"top: 10px; right: 40px; z-index: 10\"\n >\n {{ 'New' | translate }}\n </span>\n }\n\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n [title]=\"title\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"typeahead-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal\"\n [style.width]=\"container === 'body' ? searchControl.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"typeahead--dropdown-menu\"\n *dropdownMenu\n >\n <ng-content select=\"div, c8y-li, c8y-list-item, button, a\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
18427
+ ], changeDetection: ChangeDetectionStrategy.Eager, template: "@let placeholderText = placeholder ? (placeholder | translate) : null;\n@let fallbackLabel = placeholderText ? placeholderText : (title | translate);\n@let inputLabel = ariaLabelledby ? null : ariaLabel ? ariaLabel : fallbackLabel;\n\n<!-- role=\"group\" legalizes the aria dropdownToggle sets here; the button below carries the state. -->\n<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n role=\"group\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n [isDisabled]=\"disabled\"\n dropdownToggle\n>\n <div class=\"input-group input-group-dropdown\">\n <input\n class=\"form-control text-truncate\"\n [attr.aria-label]=\"inputLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n type=\"text\"\n #searchControl\n #searchControlModel=\"ngModel\"\n [ngClass]=\"{\n 'p-r-80':\n !hideNew &&\n (selected\n ? selected.id === null && getDisplayProperty()?.length > 0 && allowFreeEntries\n : false),\n 'p-r-40': hideNew || getDisplayProperty()?.length === 0\n }\"\n [required]=\"required\"\n [ngModel]=\"selected ? getDisplayProperty() : ''\"\n [attr.placeholder]=\"placeholderText\"\n (blur)=\"doBlur()\"\n [name]=\"name\"\n [maxlength]=\"maxlength\"\n [disabled]=\"disabled\"\n />\n @if (\n !hideNew &&\n selected &&\n selected.id === null &&\n getDisplayProperty()?.length > 0 &&\n allowFreeEntries\n ) {\n <span\n class=\"label label-info p-absolute\"\n style=\"top: 10px; right: 40px; z-index: 10\"\n >\n {{ 'New' | translate }}\n </span>\n }\n\n <span class=\"input-group-btn\">\n <button\n class=\"btn btn-dot\"\n [title]=\"title\"\n [attr.aria-expanded]=\"dropdown.isOpen\"\n [attr.aria-controls]=\"popupId\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"typeahead-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal\"\n [style.width]=\"container === 'body' ? searchControl.clientWidth + 'px' : undefined\"\n [id]=\"popupId\"\n data-cy=\"typeahead--dropdown-menu\"\n (click)=\"onMenuClick()\"\n *dropdownMenu\n >\n <ng-content select=\"div, c8y-li, c8y-list-item, button, a\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
18147
18428
  }], ctorParameters: () => [{ type: SelectKeyboardService }], propDecorators: { searchControl: [{
18148
18429
  type: ViewChild,
18149
18430
  args: ['searchControl', { static: false }]
@@ -18182,6 +18463,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
18182
18463
  type: Input
18183
18464
  }], title: [{
18184
18465
  type: Input
18466
+ }], ariaLabel: [{
18467
+ type: Input
18468
+ }], ariaLabelledby: [{
18469
+ type: Input
18185
18470
  }], highlightFirstItem: [{
18186
18471
  type: Input
18187
18472
  }], onSearch: [{
@@ -18687,7 +18972,7 @@ class SearchInputComponent {
18687
18972
  this.isLoading = term.length > 0;
18688
18973
  }
18689
18974
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SearchInputComponent, deps: [{ token: i1$3.Router }, { token: i1.InventoryService }, { token: InventorySearchService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
18690
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: SearchInputComponent, isStandalone: true, selector: "c8y-search-input", inputs: { mode: "mode", enableCustomTemplatePlaceholder: "enableCustomTemplatePlaceholder", customPlaceholder: "customPlaceholder", externalTerm: "externalTerm", customDataQuery: "customDataQuery", container: "container", groupsOnly: "groupsOnly" }, outputs: { filter: "filter", search: "search", reset: "reset", onClick: "onClick", onOpenToggle: "onOpenToggle" }, host: { listeners: { "document:keydown": "onKeydownHandler($event)" } }, viewQueries: [{ propertyName: "typeahead", first: true, predicate: TypeaheadComponent, descendants: true }, { propertyName: "dropdown", first: true, predicate: ["searchDropdown"], descendants: true }], ngImport: i0, template: "@if (mode === 'search' || mode === 'wildcardsearch') {\n <div\n class=\"dropdown\"\n #searchDropdown=\"bs-dropdown\"\n [insideClick]=\"true\"\n (isOpenChange)=\"onOpenChange($event)\"\n [cdkTrapFocus]=\"searchDropdown.isOpen\"\n dropdown\n >\n <button\n class=\"main-header-button dropdown-toggle c8y-dropdown\"\n [title]=\"'Search' | translate\"\n type=\"button\"\n dropdownToggle\n data-cy=\"search-input--search-btn\"\n >\n <i\n class=\"icon-2x\"\n c8yIcon=\"search\"\n ></i>\n </button>\n\n <div\n class=\"search-header-menu dropdown-menu dropdown-menu-right\"\n id=\"searchDropdown\"\n *dropdownMenu\n >\n <ng-container *ngTemplateOutlet=\"form\"></ng-container>\n </div>\n </div>\n}\n\n@if (mode === 'select') {\n <div class=\"search-header-inline\">\n <ng-container *ngTemplateOutlet=\"form\"></ng-container>\n </div>\n}\n<ng-template #form>\n <form\n [ngClass]=\"{ 'c8y-search-form': mode === 'search' || mode === 'wildcardsearch' }\"\n novalidate\n #searchForm=\"ngForm\"\n >\n <c8y-typeahead\n (onIconClick)=\"onReset($event)\"\n [icon]=\"term ? 'times' : 'search'\"\n [title]=\"(term ? RESET_TEXT : SEARCH_TEXT) | translate\"\n placeholder=\"{{ customPlaceholder ? customPlaceholder : defaultPlaceholder }}\"\n name=\"selected\"\n [(ngModel)]=\"selected\"\n (keydown)=\"keyDown($event)\"\n [allowFreeEntries]=\"false\"\n [container]=\"container\"\n [highlightFirstItem]=\"false\"\n [ngClass]=\"{ 'input-group-search input-group-lg': mode !== 'select' }\"\n >\n @if (enableCustomTemplatePlaceholder) {\n <div>\n <ng-content></ng-content>\n </div>\n }\n\n <!-- filter buttons -->\n @if (term.length !== 0 && mode === 'search') {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"d-flex\">\n <p class=\"m-r-4 text-muted\">\n <em translate>Searching by exact match. Click for other search options:</em>\n </p>\n <div class=\"btn-group btn-group-sm\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Starts with' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-starts-with\"\n (click)=\"onFilter(term + '*')\"\n >\n {{ 'Starts with' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Contains' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-contains\"\n (click)=\"onFilter('*' + term + '*')\"\n >\n {{ 'Contains' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Ends with' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-ends-with\"\n (click)=\"onFilter('*' + term)\"\n >\n {{ 'Ends with' | translate }}\n </button>\n </div>\n </div>\n </c8y-li>\n }\n\n <!-- Recent search -->\n @if (term.length === 0 && recentSearchResults.length > 0) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Recent search views\n </span>\n </div>\n </c8y-li>\n }\n @for (result of term.length === 0 ? recentSearchResults : []; track result.id) {\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n (click)=\"open($event, result, result.name)\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n }\n\n <!-- Recently registered devices -->\n @if (\n term.length === 0 && (recentlyRegisteredResults$ | async)?.data?.length > 0 && !groupsOnly\n ) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Recently registered devices\n </span>\n </div>\n </c8y-li>\n }\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n *c8yFor=\"\n let result of term.length === 0 && !groupsOnly\n ? recentlyRegisteredResults$\n : { data: [] };\n loadMore: 'none'\n \"\n (click)=\"open($event, result, result.name)\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n\n <!-- Search results -->\n @if (term.length !== 0) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Search results\n </span>\n </div>\n </c8y-li>\n }\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n [title]=\"result.name\"\n *c8yFor=\"\n let result of results$;\n loadMore: 'auto';\n notFound: notFoundTemplate;\n loadingTemplate: loading;\n loadNextLabel: 'Find more\u2026'\n \"\n (click)=\"open($event, result, result.name)\"\n data-cy=\"search-input--search-results\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n\n <!-- No search results found entry -->\n <ng-template #notFoundTemplate>\n @if (noMatch) {\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No match found.' | translate\"\n data-cy=\"search-input--empty-state\"\n [ngClass]=\"{ 'p-4': mode === 'search' || mode === 'wildcardsearch' }\"\n [horizontal]=\"true\"\n >\n @if (mode === 'search') {\n <small translate>\n Try to filter or open the asset grid to show all devices and groups.\n </small>\n }\n @if (mode === 'select' || mode === 'wildcardsearch') {\n <small translate>Try to rephrase your search word.</small>\n }\n </c8y-ui-empty-state>\n }\n </ng-template>\n\n <!-- loading bar first entries -->\n @if (isLoading) {\n <c8y-li>\n <c8y-loading></c8y-loading>\n </c8y-li>\n }\n\n <!-- loading bar for loading more entries (inventory roles) -->\n <ng-template #loading>\n <c8y-li>\n <c8y-loading></c8y-loading>\n </c8y-li>\n </ng-template>\n\n <!-- more filter possibilities -->\n @if (mode === 'search' || mode === 'wildcardsearch') {\n <c8y-li\n class=\"m-t-24 bg-level-2 p-t-16 p-b-16 p-l-24 p-r-24 sticky-bottom\"\n [selectable]=\"false\"\n >\n <div class=\"d-flex a-i-center\">\n <i\n class=\"text-info m-r-4\"\n c8yIcon=\"info-circle\"\n ></i>\n <p\n class=\"m-r-8\"\n translate\n >\n Need more filter possibilities?\n </p>\n <button\n class=\"m-l-16 btn btn-default btn-sm\"\n title=\"{{ 'Go to the asset data table' | translate }}\"\n type=\"button\"\n (mousedown)=\"onOpenAssetTable()\"\n data-cy=\"search-input--asset-table-btn\"\n >\n {{ 'Go to the asset data table' | translate }}\n </button>\n </div>\n </c8y-li>\n }\n </c8y-typeahead>\n </form>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: DeviceStatusComponent, selector: "device-status, c8y-device-status", inputs: ["mo", "size"] }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: ShouldShowMoPipe, name: "shouldShowMo" }, { kind: "pipe", type: GetGroupIconPipe, name: "getGroupIcon" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
18975
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: SearchInputComponent, isStandalone: true, selector: "c8y-search-input", inputs: { mode: "mode", enableCustomTemplatePlaceholder: "enableCustomTemplatePlaceholder", customPlaceholder: "customPlaceholder", externalTerm: "externalTerm", customDataQuery: "customDataQuery", container: "container", groupsOnly: "groupsOnly" }, outputs: { filter: "filter", search: "search", reset: "reset", onClick: "onClick", onOpenToggle: "onOpenToggle" }, host: { listeners: { "document:keydown": "onKeydownHandler($event)" } }, viewQueries: [{ propertyName: "typeahead", first: true, predicate: TypeaheadComponent, descendants: true }, { propertyName: "dropdown", first: true, predicate: ["searchDropdown"], descendants: true }], ngImport: i0, template: "@if (mode === 'search' || mode === 'wildcardsearch') {\n <div\n class=\"dropdown\"\n #searchDropdown=\"bs-dropdown\"\n [insideClick]=\"true\"\n (isOpenChange)=\"onOpenChange($event)\"\n [cdkTrapFocus]=\"searchDropdown.isOpen\"\n dropdown\n >\n <button\n class=\"main-header-button dropdown-toggle c8y-dropdown\"\n [title]=\"'Search' | translate\"\n type=\"button\"\n dropdownToggle\n data-cy=\"search-input--search-btn\"\n >\n <i\n class=\"icon-2x\"\n c8yIcon=\"search\"\n ></i>\n </button>\n\n <div\n class=\"search-header-menu dropdown-menu dropdown-menu-right\"\n id=\"searchDropdown\"\n *dropdownMenu\n >\n <ng-container *ngTemplateOutlet=\"form\"></ng-container>\n </div>\n </div>\n}\n\n@if (mode === 'select') {\n <div class=\"search-header-inline\">\n <ng-container *ngTemplateOutlet=\"form\"></ng-container>\n </div>\n}\n<ng-template #form>\n <form\n [ngClass]=\"{ 'c8y-search-form': mode === 'search' || mode === 'wildcardsearch' }\"\n novalidate\n #searchForm=\"ngForm\"\n >\n <c8y-typeahead\n (onIconClick)=\"onReset($event)\"\n [icon]=\"term ? 'times' : 'search'\"\n [title]=\"(term ? RESET_TEXT : SEARCH_TEXT) | translate\"\n placeholder=\"{{ customPlaceholder ? customPlaceholder : defaultPlaceholder }}\"\n name=\"selected\"\n [(ngModel)]=\"selected\"\n (keydown)=\"keyDown($event)\"\n [allowFreeEntries]=\"false\"\n [container]=\"container\"\n [highlightFirstItem]=\"false\"\n [ngClass]=\"{ 'input-group-search input-group-lg': mode !== 'select' }\"\n >\n @if (enableCustomTemplatePlaceholder) {\n <div>\n <ng-content></ng-content>\n </div>\n }\n\n <!-- filter buttons -->\n @if (term.length !== 0 && mode === 'search') {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"d-flex\">\n <p class=\"m-r-4 text-muted\">\n <em translate>Searching by exact match. Click for other search options:</em>\n </p>\n <div class=\"btn-group btn-group-sm\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Starts with' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-starts-with\"\n (click)=\"onFilter(term + '*')\"\n >\n {{ 'Starts with' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Contains' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-contains\"\n (click)=\"onFilter('*' + term + '*')\"\n >\n {{ 'Contains' | translate }}\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Ends with' | translate }}\"\n type=\"button\"\n data-cy=\"search-input--search-ends-with\"\n (click)=\"onFilter('*' + term)\"\n >\n {{ 'Ends with' | translate }}\n </button>\n </div>\n </div>\n </c8y-li>\n }\n\n <!-- Recent search -->\n @if (term.length === 0 && recentSearchResults.length > 0) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Recent search views\n </span>\n </div>\n </c8y-li>\n }\n @for (result of term.length === 0 ? recentSearchResults : []; track result.id) {\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n (click)=\"open($event, result, result.name)\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n }\n\n <!-- Recently registered devices -->\n @if (\n term.length === 0 && (recentlyRegisteredResults$ | async)?.data?.length > 0 && !groupsOnly\n ) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Recently registered devices\n </span>\n </div>\n </c8y-li>\n }\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n *c8yFor=\"\n let result of term.length === 0 && !groupsOnly\n ? recentlyRegisteredResults$\n : { data: [] };\n loadMore: 'none'\n \"\n (click)=\"open($event, result, result.name)\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n\n <!-- Search results -->\n @if (term.length !== 0) {\n <c8y-li\n class=\"m-l-32 m-r-32\"\n [selectable]=\"false\"\n >\n <div class=\"legend\">\n <span\n class=\"text-bold text-muted\"\n translate\n >\n Search results\n </span>\n </div>\n </c8y-li>\n }\n <c8y-li\n class=\"c8y-list__item--link m-l-32 m-r-32\"\n [title]=\"result.name\"\n *c8yFor=\"\n let result of results$;\n loadMore: 'auto';\n notFound: notFoundTemplate;\n loadingTemplate: loading;\n loadNextLabel: 'Find more\u2026'\n \"\n (click)=\"open($event, result, result.name)\"\n data-cy=\"search-input--search-results\"\n >\n <c8y-li-icon>\n @if (result | shouldShowMo: deviceType.DEVICE) {\n <device-status [mo]=\"result\"></device-status>\n } @else {\n <i\n class=\"c8y-icon-duocolor\"\n [c8yIcon]=\"result | getGroupIcon | async\"\n ></i>\n }\n </c8y-li-icon>\n {{ result.name || '--' }}\n </c8y-li>\n\n <!-- No search results found entry -->\n <ng-template #notFoundTemplate>\n @if (noMatch) {\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No match found.' | translate\"\n data-cy=\"search-input--empty-state\"\n [ngClass]=\"{ 'p-4': mode === 'search' || mode === 'wildcardsearch' }\"\n [horizontal]=\"true\"\n >\n @if (mode === 'search') {\n <small translate>\n Try to filter or open the asset grid to show all devices and groups.\n </small>\n }\n @if (mode === 'select' || mode === 'wildcardsearch') {\n <small translate>Try to rephrase your search word.</small>\n }\n </c8y-ui-empty-state>\n }\n </ng-template>\n\n <!-- loading bar first entries -->\n @if (isLoading) {\n <c8y-li>\n <c8y-loading></c8y-loading>\n </c8y-li>\n }\n\n <!-- loading bar for loading more entries (inventory roles) -->\n <ng-template #loading>\n <c8y-li>\n <c8y-loading></c8y-loading>\n </c8y-li>\n </ng-template>\n\n <!-- more filter possibilities -->\n @if (mode === 'search' || mode === 'wildcardsearch') {\n <c8y-li\n class=\"m-t-24 bg-level-2 p-t-16 p-b-16 p-l-24 p-r-24 sticky-bottom\"\n [selectable]=\"false\"\n >\n <div class=\"d-flex a-i-center\">\n <i\n class=\"text-info m-r-4\"\n c8yIcon=\"info-circle\"\n ></i>\n <p\n class=\"m-r-8\"\n translate\n >\n Need more filter possibilities?\n </p>\n <button\n class=\"m-l-16 btn btn-default btn-sm\"\n title=\"{{ 'Go to the asset data table' | translate }}\"\n type=\"button\"\n (mousedown)=\"onOpenAssetTable()\"\n data-cy=\"search-input--asset-table-btn\"\n >\n {{ 'Go to the asset data table' | translate }}\n </button>\n </div>\n </c8y-li>\n }\n </c8y-typeahead>\n </form>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "ariaLabel", "ariaLabelledby", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable", "selectOnClick"], outputs: ["collapsedChange"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: DeviceStatusComponent, selector: "device-status, c8y-device-status", inputs: ["mo", "size"] }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: ShouldShowMoPipe, name: "shouldShowMo" }, { kind: "pipe", type: GetGroupIconPipe, name: "getGroupIcon" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
18691
18976
  }
18692
18977
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SearchInputComponent, decorators: [{
18693
18978
  type: Component,
@@ -18978,6 +19263,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
18978
19263
  type: Input
18979
19264
  }] } });
18980
19265
 
19266
+ /**
19267
+ * What `c8y-li-radio` and `c8y-li-checkbox` share, applied to both as a host directive: the
19268
+ * accessible name of the control, and the connection to the `c8y-li` it renders in, which names an
19269
+ * unnamed control after the row content and selects the control on a row click.
19270
+ */
19271
+ class ListItemSelectionControlDirective {
19272
+ constructor() {
19273
+ this.host = inject(ElementRef);
19274
+ this.listItem = inject(ListItemSelectionHost, { optional: true });
19275
+ }
19276
+ /**
19277
+ * The native input the control renders, so that its list item can select it on the user's behalf.
19278
+ */
19279
+ get input() {
19280
+ return new ElementRef(this.host.nativeElement.querySelector('input'));
19281
+ }
19282
+ ngOnInit() {
19283
+ this.listItem?.registerSelectionControl(this);
19284
+ }
19285
+ ngOnDestroy() {
19286
+ this.listItem?.unregisterSelectionControl(this);
19287
+ }
19288
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemSelectionControlDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
19289
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.19", type: ListItemSelectionControlDirective, isStandalone: true, inputs: { ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledBy: ["aria-labelledby", "ariaLabelledBy"] }, host: { properties: { "attr.aria-label": "null" } }, ngImport: i0 }); }
19290
+ }
19291
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemSelectionControlDirective, decorators: [{
19292
+ type: Directive,
19293
+ args: [{
19294
+ standalone: true,
19295
+ host: {
19296
+ // the name belongs on the input; on the host element it is a prohibited attribute, whether the
19297
+ // author sets it statically or binds it
19298
+ '[attr.aria-label]': 'null'
19299
+ }
19300
+ }]
19301
+ }], propDecorators: { ariaLabel: [{
19302
+ type: Input,
19303
+ args: ['aria-label']
19304
+ }], ariaLabelledBy: [{
19305
+ type: Input,
19306
+ args: ['aria-labelledby']
19307
+ }] } });
19308
+
18981
19309
  /**
18982
19310
  * A component to display checkboxes in a c8y-li. Use it with content projection. It
18983
19311
  * can be used standalone or with an ngModel.
@@ -18991,8 +19319,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
18991
19319
  class ListItemCheckboxComponent extends CheckboxControlValueAccessor {
18992
19320
  constructor(renderer, elementRef) {
18993
19321
  super(renderer, elementRef);
18994
- this.renderer = renderer;
18995
- this.elementRef = elementRef;
18996
19322
  /**
18997
19323
  * Indicates if the checkbox is selected.
18998
19324
  */
@@ -19009,6 +19335,11 @@ class ListItemCheckboxComponent extends CheckboxControlValueAccessor {
19009
19335
  * Allows to display the chceckbox as a switch
19010
19336
  */
19011
19337
  this.displayAsSwitch = false;
19338
+ /**
19339
+ * Names the checkbox and connects it to its list item.
19340
+ * @ignore
19341
+ */
19342
+ this.naming = inject(ListItemSelectionControlDirective);
19012
19343
  }
19013
19344
  /**
19014
19345
  * @ignore
@@ -19042,7 +19373,7 @@ class ListItemCheckboxComponent extends CheckboxControlValueAccessor {
19042
19373
  multi: true,
19043
19374
  useExisting: forwardRef(() => ListItemCheckboxComponent)
19044
19375
  }
19045
- ], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<label [ngClass]=\"displayAsSwitch ? 'c8y-switch c8y-switch--inline' : 'c8y-checkbox'\">\n <input\n type=\"checkbox\"\n class=\"form-control\"\n [disabled]=\"disabled\"\n [checked]=\"selected\"\n (change)=\"select($event.target.checked); (false)\"\n [indeterminate]=\"indeterminate\"\n />\n <span></span>\n <span class=\"sr-only\">event</span>\n</label>\n<ng-content></ng-content>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
19376
+ ], viewQueries: [{ propertyName: "checkbox", first: true, predicate: ["checkbox"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: ListItemSelectionControlDirective, inputs: ["aria-label", "aria-label", "aria-labelledby", "aria-labelledby"] }], ngImport: i0, template: "<label [ngClass]=\"displayAsSwitch ? 'c8y-switch c8y-switch--inline' : 'c8y-checkbox'\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"naming.ariaLabel\"\n [attr.aria-labelledby]=\"naming.ariaLabel ? null : naming.ariaLabelledBy\"\n type=\"checkbox\"\n #checkbox\n [disabled]=\"disabled\"\n [checked]=\"selected\"\n (change)=\"select($event.target.checked); (false)\"\n [indeterminate]=\"indeterminate\"\n />\n <span></span>\n</label>\n<ng-content></ng-content>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
19046
19377
  }
19047
19378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemCheckboxComponent, decorators: [{
19048
19379
  type: Component,
@@ -19054,8 +19385,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
19054
19385
  multi: true,
19055
19386
  useExisting: forwardRef(() => ListItemCheckboxComponent)
19056
19387
  }
19057
- ], standalone: true, imports: [NgClass], changeDetection: ChangeDetectionStrategy.Eager, template: "<label [ngClass]=\"displayAsSwitch ? 'c8y-switch c8y-switch--inline' : 'c8y-checkbox'\">\n <input\n type=\"checkbox\"\n class=\"form-control\"\n [disabled]=\"disabled\"\n [checked]=\"selected\"\n (change)=\"select($event.target.checked); (false)\"\n [indeterminate]=\"indeterminate\"\n />\n <span></span>\n <span class=\"sr-only\">event</span>\n</label>\n<ng-content></ng-content>\n" }]
19058
- }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { selected: [{
19388
+ ], hostDirectives: [
19389
+ { directive: ListItemSelectionControlDirective, inputs: ['aria-label', 'aria-labelledby'] }
19390
+ ], standalone: true, imports: [NgClass], changeDetection: ChangeDetectionStrategy.Eager, template: "<label [ngClass]=\"displayAsSwitch ? 'c8y-switch c8y-switch--inline' : 'c8y-checkbox'\">\n <input\n class=\"form-control\"\n [attr.aria-label]=\"naming.ariaLabel\"\n [attr.aria-labelledby]=\"naming.ariaLabel ? null : naming.ariaLabelledBy\"\n type=\"checkbox\"\n #checkbox\n [disabled]=\"disabled\"\n [checked]=\"selected\"\n (change)=\"select($event.target.checked); (false)\"\n [indeterminate]=\"indeterminate\"\n />\n <span></span>\n</label>\n<ng-content></ng-content>\n" }]
19391
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { checkbox: [{
19392
+ type: ViewChild,
19393
+ args: ['checkbox', { static: true }]
19394
+ }], selected: [{
19059
19395
  type: Input
19060
19396
  }], indeterminate: [{
19061
19397
  type: Input
@@ -19097,10 +19433,6 @@ class ListItemRadioComponent {
19097
19433
  * Indicates if the radio is selected.
19098
19434
  */
19099
19435
  this.selected = false;
19100
- /**
19101
- * The name of the radio (use different names for different radio groups).
19102
- */
19103
- this.name = 'list_item_radio';
19104
19436
  /**
19105
19437
  * Indicates if the radio is disabled.
19106
19438
  */
@@ -19109,6 +19441,22 @@ class ListItemRadioComponent {
19109
19441
  * An event emitted as soon as the radio is selected.
19110
19442
  */
19111
19443
  this.onSelect = new EventEmitter();
19444
+ this._name = 'list_item_radio';
19445
+ /**
19446
+ * Names the radio and connects it to its list item.
19447
+ * @ignore
19448
+ */
19449
+ this.naming = inject(ListItemSelectionControlDirective);
19450
+ }
19451
+ /**
19452
+ * The name of the radio (use different names for different radio groups). Radios sharing a name
19453
+ * form one group: the group is a single tab stop and the arrow keys move between its options.
19454
+ */
19455
+ set name(name) {
19456
+ this._name = name || 'list_item_radio';
19457
+ }
19458
+ get name() {
19459
+ return this._name;
19112
19460
  }
19113
19461
  /**
19114
19462
  * Resets the native radio element.
@@ -19163,7 +19511,7 @@ class ListItemRadioComponent {
19163
19511
  multi: true,
19164
19512
  useExisting: forwardRef(() => ListItemRadioComponent)
19165
19513
  }
19166
- ], viewQueries: [{ propertyName: "radio", first: true, predicate: ["radio"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<label class=\"c8y-radio\">\n <input\n #radio\n id=\"event\"\n type=\"radio\"\n [name]=\"name\"\n [checked]=\"selected\"\n (change)=\"change($event.target.checked); (false)\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <span for=\"event\" class=\"sr-only\" translate>event</span>\n</label>\n<ng-content></ng-content>\n", dependencies: [{ kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
19514
+ ], viewQueries: [{ propertyName: "radio", first: true, predicate: ["radio"], descendants: true, static: true }], usesOnChanges: true, hostDirectives: [{ directive: ListItemSelectionControlDirective, inputs: ["aria-label", "aria-label", "aria-labelledby", "aria-labelledby"] }], ngImport: i0, template: "<label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"naming.ariaLabel\"\n [attr.aria-labelledby]=\"naming.ariaLabel ? null : naming.ariaLabelledBy\"\n type=\"radio\"\n #radio\n [name]=\"name\"\n [checked]=\"selected\"\n (change)=\"change($event.target.checked); (false)\"\n [disabled]=\"disabled\"\n />\n <span></span>\n</label>\n<ng-content></ng-content>\n", changeDetection: i0.ChangeDetectionStrategy.Eager }); }
19167
19515
  }
19168
19516
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ListItemRadioComponent, decorators: [{
19169
19517
  type: Component,
@@ -19175,7 +19523,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
19175
19523
  multi: true,
19176
19524
  useExisting: forwardRef(() => ListItemRadioComponent)
19177
19525
  }
19178
- ], standalone: true, imports: [C8yTranslateDirective], changeDetection: ChangeDetectionStrategy.Eager, template: "<label class=\"c8y-radio\">\n <input\n #radio\n id=\"event\"\n type=\"radio\"\n [name]=\"name\"\n [checked]=\"selected\"\n (change)=\"change($event.target.checked); (false)\"\n [disabled]=\"disabled\"\n />\n <span></span>\n <span for=\"event\" class=\"sr-only\" translate>event</span>\n</label>\n<ng-content></ng-content>\n" }]
19526
+ ], hostDirectives: [
19527
+ { directive: ListItemSelectionControlDirective, inputs: ['aria-label', 'aria-labelledby'] }
19528
+ ], standalone: true, changeDetection: ChangeDetectionStrategy.Eager, template: "<label class=\"c8y-radio\">\n <input\n [attr.aria-label]=\"naming.ariaLabel\"\n [attr.aria-labelledby]=\"naming.ariaLabel ? null : naming.ariaLabelledBy\"\n type=\"radio\"\n #radio\n [name]=\"name\"\n [checked]=\"selected\"\n (change)=\"change($event.target.checked); (false)\"\n [disabled]=\"disabled\"\n />\n <span></span>\n</label>\n<ng-content></ng-content>\n" }]
19179
19529
  }], propDecorators: { radio: [{
19180
19530
  type: ViewChild,
19181
19531
  args: ['radio', { static: true }]
@@ -20913,6 +21263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
20913
21263
  }]
20914
21264
  }] });
20915
21265
 
21266
+ let nextUniqueId = 0;
20916
21267
  class SelectComponent {
20917
21268
  /**
20918
21269
  * Items to be displayed in the select.
@@ -21049,6 +21400,11 @@ class SelectComponent {
21049
21400
  * Indicates if the search input has focus.
21050
21401
  */
21051
21402
  this.searchHasFocus = false;
21403
+ /**
21404
+ * Id of the dropdown popup. The toggle button references it via `aria-controls`.
21405
+ * @ignore
21406
+ */
21407
+ this.popupId = `c8y-select-popup-${nextUniqueId++}`;
21052
21408
  /**
21053
21409
  * The internal select element.
21054
21410
  * @ignore
@@ -21060,6 +21416,17 @@ class SelectComponent {
21060
21416
  */
21061
21417
  this._items = [];
21062
21418
  this.destroy$ = new Subject();
21419
+ /**
21420
+ * Set while focus is moved back to the input programmatically, so that the
21421
+ * focus handler does not reopen the dropdown that just closed.
21422
+ */
21423
+ this.suppressOpenOnFocus = false;
21424
+ /**
21425
+ * Set by a click inside the menu. Clicking a list item drops focus to the
21426
+ * body (or to a hosting modal) because the item is not focusable and the menu
21427
+ * is removed on close, so `onHidden` brings focus back to the input.
21428
+ */
21429
+ this.restoreFocusOnHide = false;
21063
21430
  this.selectKeyboardService.options = {
21064
21431
  emptyInput: !this.filterItems,
21065
21432
  keyboardSearch: true,
@@ -21191,6 +21558,19 @@ class SelectComponent {
21191
21558
  open() {
21192
21559
  this.dropdown.show();
21193
21560
  }
21561
+ /**
21562
+ * Moves focus to the search input without opening the dropdown, for example
21563
+ * to focus the first control of a modal. Use `open()` to show the items.
21564
+ */
21565
+ focus() {
21566
+ this.suppressOpenOnFocus = true;
21567
+ try {
21568
+ this.searchControl.nativeElement.focus();
21569
+ }
21570
+ finally {
21571
+ this.suppressOpenOnFocus = false;
21572
+ }
21573
+ }
21194
21574
  /**
21195
21575
  * @ignore
21196
21576
  * @param value The value to write.
@@ -21234,11 +21614,23 @@ class SelectComponent {
21234
21614
  * @ignore
21235
21615
  */
21236
21616
  doFocus() {
21237
- this.open();
21617
+ if (!this.suppressOpenOnFocus) {
21618
+ this.open();
21619
+ }
21238
21620
  queueMicrotask(() => {
21239
21621
  this.searchHasFocus = true;
21240
21622
  });
21241
21623
  }
21624
+ /**
21625
+ * Remembers that the menu was clicked, so focus can be restored once the
21626
+ * click has closed the dropdown. Skipped when clicks keep the menu open.
21627
+ * @ignore
21628
+ */
21629
+ onMenuClick() {
21630
+ if (!this.insideClick) {
21631
+ this.restoreFocusOnHide = true;
21632
+ }
21633
+ }
21242
21634
  /**
21243
21635
  * @ignore
21244
21636
  */
@@ -21253,6 +21645,7 @@ class SelectComponent {
21253
21645
  * @ignore
21254
21646
  */
21255
21647
  onShown() {
21648
+ this.restoreFocusOnHide = false;
21256
21649
  this.searchControl.nativeElement.focus();
21257
21650
  }
21258
21651
  /**
@@ -21262,6 +21655,10 @@ class SelectComponent {
21262
21655
  onHidden() {
21263
21656
  this.searchControl.nativeElement.value = '';
21264
21657
  this._preselectedItem = null;
21658
+ if (this.restoreFocusOnHide) {
21659
+ this.restoreFocusOnHide = false;
21660
+ this.focus();
21661
+ }
21265
21662
  }
21266
21663
  emitChangeEvent() {
21267
21664
  if (typeof this.onChange === 'function') {
@@ -21283,7 +21680,7 @@ class SelectComponent {
21283
21680
  : requiredText;
21284
21681
  }
21285
21682
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SelectComponent, deps: [{ token: SelectKeyboardService }, { token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
21286
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: SelectComponent, isStandalone: true, selector: "c8y-select", inputs: { placeholder: "placeholder", items: "items", selected: "selected", container: "container", multi: "multi", canSelectWithSpace: "canSelectWithSpace", disabled: "disabled", autoClose: "autoClose", insideClick: "insideClick", required: "required", canDeselect: "canDeselect", name: "name", icon: "icon", filterItems: "filterItems" }, outputs: { onSelect: "onSelect", onDeselect: "onDeselect", onIconClick: "onIconClick" }, host: { classAttribute: "c8y-select-v2" }, providers: [
21683
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: SelectComponent, isStandalone: true, selector: "c8y-select", inputs: { placeholder: "placeholder", items: "items", selected: "selected", container: "container", multi: "multi", canSelectWithSpace: "canSelectWithSpace", disabled: "disabled", autoClose: "autoClose", insideClick: "insideClick", required: "required", canDeselect: "canDeselect", name: "name", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", icon: "icon", filterItems: "filterItems" }, outputs: { onSelect: "onSelect", onDeselect: "onDeselect", onIconClick: "onIconClick" }, host: { classAttribute: "c8y-select-v2" }, providers: [
21287
21684
  {
21288
21685
  provide: NG_VALUE_ACCESSOR,
21289
21686
  multi: true,
@@ -21295,7 +21692,7 @@ class SelectComponent {
21295
21692
  multi: true
21296
21693
  },
21297
21694
  SelectKeyboardService
21298
- ], queries: [{ propertyName: "projectedSelectedItems", first: true, predicate: SelectedItemsDirective, descendants: true }, { propertyName: "projectedSelectableItems", predicate: SelectItemDirective }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "list", predicate: ListItemComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: FilterByPipe, name: "filterBy" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
21695
+ ], queries: [{ propertyName: "projectedSelectedItems", first: true, predicate: SelectedItemsDirective, descendants: true }, { propertyName: "projectedSelectableItems", predicate: SelectItemDirective }], viewQueries: [{ propertyName: "searchControl", first: true, predicate: ["searchControl"], descendants: true }, { propertyName: "dropdown", first: true, predicate: ["dropdown"], descendants: true }, { propertyName: "list", predicate: ListItemComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@let inputLabel = ariaLabelledby ? null : ariaLabel ? ariaLabel : displayPlaceholder;\n\n<!-- role=\"group\" legalizes the aria dropdownToggle sets here; the button below carries the state. -->\n<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n role=\"group\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div class=\"input-group input-group-dropdown\">\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !dropdown.isOpen && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <!-- keyed on the open state, not on focus: the input keeps focus after the menu closes -->\n <span [hidden]=\"!dropdown.isOpen || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span\n data-cy=\"select--selected-label\"\n [hidden]=\"dropdown.isOpen || selected.length !== 1\"\n >\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n [attr.aria-label]=\"inputLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n [attr.aria-expanded]=\"dropdown.isOpen\"\n [attr.aria-controls]=\"popupId\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n [id]=\"popupId\"\n data-cy=\"select--dropdown-menu\"\n (click)=\"onMenuClick()\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n", dependencies: [{ kind: "ngmodule", type: BsDropdownModule }, { kind: "directive", type: i1$2.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i1$2.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i1$2.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable", "selectOnClick"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemCheckboxComponent, selector: "c8y-list-item-checkbox, c8y-li-checkbox", inputs: ["selected", "indeterminate", "disabled", "displayAsSwitch"], outputs: ["onSelect"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: FilterByPipe, name: "filterBy" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
21299
21696
  }
21300
21697
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SelectComponent, decorators: [{
21301
21698
  type: Component,
@@ -21323,7 +21720,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
21323
21720
  ListItemBodyComponent,
21324
21721
  C8yTranslatePipe,
21325
21722
  FilterByPipe
21326
- ], changeDetection: ChangeDetectionStrategy.Eager, template: "<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div\n class=\"input-group input-group-dropdown\"\n role=\"button\"\n >\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !searchHasFocus && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <span [hidden]=\"!searchHasFocus || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span [hidden]=\"searchHasFocus || selected.length !== 1\">\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n role=\"menu\"\n data-cy=\"select--dropdown-menu\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
21723
+ ], changeDetection: ChangeDetectionStrategy.Eager, template: "@let inputLabel = ariaLabelledby ? null : ariaLabel ? ariaLabel : displayPlaceholder;\n\n<!-- role=\"group\" legalizes the aria dropdownToggle sets here; the button below carries the state. -->\n<div\n class=\"c8y-search-dropdown dropdown fit-w\"\n placement=\"bottom left\"\n role=\"group\"\n dropdown\n [container]=\"container\"\n #dropdown=\"bs-dropdown\"\n [autoClose]=\"autoClose\"\n [isDisabled]=\"disabled\"\n [insideClick]=\"insideClick\"\n (onShown)=\"onShown()\"\n (onHidden)=\"onHidden()\"\n dropdownToggle\n (click)=\"open()\"\n>\n <div class=\"input-group input-group-dropdown\">\n <div\n class=\"form-control text-truncate\"\n [ngClass]=\"{\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0,\n 'text-truncate': !multi,\n 'inner-scroll d-flex a-i-center': multi\n }\"\n >\n <!-- rendering of selected items (with content projection) -->\n @if (projectedSelectedItems) {\n <div class=\"selected-items\">\n @for (selectedItem of selected; track selectedItem) {\n <ng-container\n *ngTemplateOutlet=\"\n projectedSelectedItems.templateRef;\n context: { $implicit: selectedItem }\n \"\n ></ng-container>\n }\n </div>\n @if (selected.length === 0 && !dropdown.isOpen && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n } @else {\n <div class=\"selected-items\">\n @if (!multi) {\n <!-- hidden is needed, otherwise the propagation does not work correctly -->\n <!-- keyed on the open state, not on focus: the input keeps focus after the menu closes -->\n <span [hidden]=\"!dropdown.isOpen || !preselectedItem || filterItems\">\n {{ preselectedItem?.label | translate }}\n </span>\n <span\n data-cy=\"select--selected-label\"\n [hidden]=\"dropdown.isOpen || selected.length !== 1\"\n >\n {{ selected[0]?.label | translate }}\n </span>\n }\n @if (selected.length === 0 && !preselectedItem && searchControl.value.length === 0) {\n <i class=\"text-muted\">\n {{ displayPlaceholder }}\n </i>\n }\n @if (multi) {\n <span class=\"m-r-4\">{{ searchControl.value }}</span>\n @for (selectedItem of selected; track selectedItem) {\n <span class=\"tag tag--info chip\">\n <button\n class=\"btn btn-xs btn-clean text-10 m-r-4\"\n title=\"{{ selectedItem.label | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"\n $event.preventDefault(); $event.stopPropagation(); deselect(selectedItem)\n \"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n {{ selectedItem.label | translate }}\n </span>\n }\n }\n </div>\n }\n </div>\n\n <input\n class=\"form-control text-truncate\"\n [attr.aria-label]=\"inputLabel\"\n [attr.aria-labelledby]=\"ariaLabelledby\"\n type=\"text\"\n autocomplete=\"off\"\n #searchControl\n [ngClass]=\"{\n 'p-absolute': true,\n 'm-r-80': canDeselect && selected.length > 0,\n 'm-r-40': !canDeselect || selected.length === 0\n }\"\n [required]=\"required\"\n (blur)=\"doBlur()\"\n (focus)=\"doFocus()\"\n [name]=\"name\"\n [disabled]=\"disabled\"\n />\n\n <span class=\"input-group-btn\">\n <!-- this button is displayed only if we have something selected and are allowed to deselect -->\n @if (canDeselect && selected.length > 0) {\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Deselect' | translate }}\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"$event.preventDefault(); $event.stopPropagation(); deselectAll()\"\n data-cy=\"deselect-all-button\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n }\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Search' | translate }}\"\n [attr.aria-expanded]=\"dropdown.isOpen\"\n [attr.aria-controls]=\"popupId\"\n type=\"button\"\n [disabled]=\"disabled\"\n (click)=\"onIconClick.emit({ icon, $event })\"\n data-cy=\"select-button\"\n >\n <i\n class=\"text-primary\"\n [c8yIcon]=\"icon\"\n ></i>\n </button>\n </span>\n </div>\n\n <c8y-list-group\n class=\"dropdown-menu dropdown-menu--modal dropdown-menu--select\"\n [style.width]=\"container === 'body' ? searchControl.parentNode.clientWidth + 'px' : undefined\"\n [id]=\"popupId\"\n data-cy=\"select--dropdown-menu\"\n (click)=\"onMenuClick()\"\n *dropdownMenu\n >\n <!-- rendering of items (default) -->\n @for (item of filterItems ? (items | filterBy: searchControl.value) : items; track item) {\n <c8y-li\n style=\"cursor: pointer\"\n [selectable]=\"true\"\n [dense]=\"true\"\n [active]=\"!multi && item.value === selected[0]?.value\"\n (click)=\"select(item)\"\n >\n <span [attr.data-search-label]=\"item.label | translate\"></span>\n @if (multi) {\n <c8y-li-checkbox\n [selected]=\"selected.indexOf(item) > -1\"\n (click)=\"$event.preventDefault()\"\n ></c8y-li-checkbox>\n }\n @if (!item.template) {\n <c8y-li-body>\n {{ item.label | translate }}\n </c8y-li-body>\n }\n <ng-container\n *ngTemplateOutlet=\"item?.template\"\n ngProjectAs=\"c8y-li-body\"\n ></ng-container>\n </c8y-li>\n }\n <ng-content select=\"div\"></ng-content>\n </c8y-list-group>\n</div>\n" }]
21327
21724
  }], ctorParameters: () => [{ type: SelectKeyboardService }, { type: i1$1.TranslateService }], propDecorators: { placeholder: [{
21328
21725
  type: Input
21329
21726
  }], items: [{
@@ -21348,6 +21745,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
21348
21745
  type: Input
21349
21746
  }], name: [{
21350
21747
  type: Input
21748
+ }], ariaLabel: [{
21749
+ type: Input
21750
+ }], ariaLabelledby: [{
21751
+ type: Input
21351
21752
  }], icon: [{
21352
21753
  type: Input
21353
21754
  }], filterItems: [{
@@ -29121,7 +29522,7 @@ class TypeaheadTypeComponent extends FieldType {
29121
29522
  }));
29122
29523
  }
29123
29524
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TypeaheadTypeComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
29124
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: TypeaheadTypeComponent, isStandalone: true, selector: "c8y-typeahead-type", usesInheritance: true, ngImport: i0, template: "<c8y-typeahead\n [required]=\"to?.required || false\"\n [placeholder]=\"placeholder$ | async\"\n [displayProperty]=\"to?.displayProperty\"\n [selected]=\"selected\"\n [allowFreeEntries]=\"to?.allowFreeEntries || false\"\n [container]=\"to?.container || ''\"\n [disabled]=\"to?.disabled\"\n (onSearch)=\"setPipe($event)\"\n [formControl]=\"formControl\"\n [class.is-invalid]=\"showError\"\n [formlyAttributes]=\"field\">\n <c8y-li *c8yFor=\"let opt of to?.c8yForOptions; loadMore: to?.loadMore || 'auto'; pipe: filterPipe; notFound: notFoundTemplate; loadingTemplate: loading;\"\n (click)=\"selectOption(opt); setPipe('')\"\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n [attr.role]=\"'menuitem'\">\n <c8y-highlight [text]=\"opt[labelProp]\" [pattern]=\"pattern\"></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class=\"bg-level-2 p-8\" *ngIf=\"pattern.length > 0 && !match\">\n <p><strong translate>No match found.</strong></p>\n </c8y-li>\n </ng-template>\n <ng-template #loading>\n <c8y-li class=\"text-center p-t-8 p-relative\">\n <c8y-loading></c8y-loading>\n </c8y-li>\n </ng-template>\n</c8y-typeahead>\n", dependencies: [{ kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "directive", type: i2$5.ɵFormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29525
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: TypeaheadTypeComponent, isStandalone: true, selector: "c8y-typeahead-type", usesInheritance: true, ngImport: i0, template: "<c8y-typeahead\n [required]=\"to?.required || false\"\n [placeholder]=\"placeholder$ | async\"\n [displayProperty]=\"to?.displayProperty\"\n [selected]=\"selected\"\n [allowFreeEntries]=\"to?.allowFreeEntries || false\"\n [container]=\"to?.container || ''\"\n [disabled]=\"to?.disabled\"\n (onSearch)=\"setPipe($event)\"\n [formControl]=\"formControl\"\n [class.is-invalid]=\"showError\"\n [formlyAttributes]=\"field\">\n <c8y-li *c8yFor=\"let opt of to?.c8yForOptions; loadMore: to?.loadMore || 'auto'; pipe: filterPipe; notFound: notFoundTemplate; loadingTemplate: loading;\"\n (click)=\"selectOption(opt); setPipe('')\"\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n [attr.role]=\"'menuitem'\">\n <c8y-highlight [text]=\"opt[labelProp]\" [pattern]=\"pattern\"></c8y-highlight>\n </c8y-li>\n <ng-template #notFoundTemplate>\n <c8y-li class=\"bg-level-2 p-8\" *ngIf=\"pattern.length > 0 && !match\">\n <p><strong translate>No match found.</strong></p>\n </c8y-li>\n </ng-template>\n <ng-template #loading>\n <c8y-li class=\"text-center p-t-8 p-relative\">\n <c8y-loading></c8y-loading>\n </c8y-li>\n </ng-template>\n</c8y-typeahead>\n", dependencies: [{ kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "ariaLabel", "ariaLabelledby", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "directive", type: i2$5.ɵFormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "directive", type: ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable", "selectOnClick"], outputs: ["collapsedChange"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
29125
29526
  }
29126
29527
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: TypeaheadTypeComponent, decorators: [{
29127
29528
  type: Component,
@@ -33060,6 +33461,63 @@ function globalAutoRefreshLoading(globalRefreshService) {
33060
33461
  : globalRefreshService.decrementLoading()));
33061
33462
  }
33062
33463
 
33464
+ /**
33465
+ * Binds widget configurations to the context object currently being viewed.
33466
+ *
33467
+ * A device type dashboard is a single template shared by all devices of the type, so every asset
33468
+ * reference a widget stores has to be re-pointed at the device being viewed before the widget
33469
+ * renders. Widgets that keep those references in a shape the dashboard cannot know about implement
33470
+ * the `applyContext` hook of their definition to do it themselves.
33471
+ */
33472
+ class WidgetContextBindingService {
33473
+ constructor() {
33474
+ this.dynamic = inject(DynamicComponentService);
33475
+ }
33476
+ /**
33477
+ * Binds the configuration of each widget to the given context.
33478
+ *
33479
+ * Widgets whose definition implements the `applyContext` hook rebind themselves.
33480
+ * Falls back to the `fallback` context replacement function if:
33481
+ * - the `applyContext` hook is not defined or throws an error
33482
+ * - the widget's definition fails to load
33483
+ *
33484
+ * @param widgets The widgets to rebind, modified in place
33485
+ * @param context The managed object of the context currently being viewed
33486
+ * @param fallback Default context replacement, applied per widget when the hook does not run
33487
+ */
33488
+ async applyContextToWidgets(widgets, context, fallback) {
33489
+ await Promise.all(widgets.map(async (widget) => {
33490
+ const widgetId = widget.componentId || widget.name;
33491
+ let definition;
33492
+ try {
33493
+ definition = await this.dynamic.getById(widgetId);
33494
+ }
33495
+ catch (error) {
33496
+ console.error(`The definition of widget "${widgetId}" could not be loaded, so the widget cannot be rendered. Applying the default context replacement anyway to keep its configuration consistent.`, error);
33497
+ }
33498
+ const applyContext = definition?.data?.applyContext;
33499
+ if (typeof applyContext === 'function') {
33500
+ try {
33501
+ // A hook that returns nothing is treated as "config left as is", so that a missing
33502
+ // return value cannot wipe the widget's configuration.
33503
+ widget.config = (await applyContext(widget.config, context)) ?? widget.config;
33504
+ return;
33505
+ }
33506
+ catch (error) {
33507
+ console.error(`The applyContext hook of widget "${widgetId}" failed. Falling back to the default context replacement.`, error);
33508
+ }
33509
+ }
33510
+ fallback(widget);
33511
+ }));
33512
+ }
33513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetContextBindingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
33514
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetContextBindingService, providedIn: 'root' }); }
33515
+ }
33516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetContextBindingService, decorators: [{
33517
+ type: Injectable,
33518
+ args: [{ providedIn: 'root' }]
33519
+ }] });
33520
+
33063
33521
  class WidgetsDashboardComponent {
33064
33522
  set widgets(value) {
33065
33523
  this._widgets.next(value);
@@ -33101,7 +33559,7 @@ class WidgetsDashboardComponent {
33101
33559
  get nativeElement() {
33102
33560
  return this.elementRef.nativeElement;
33103
33561
  }
33104
- constructor(dynamic, translateService, route, modal, widgetGlobalAutoRefresh, router, elementRef) {
33562
+ constructor(dynamic, translateService, route, modal, widgetGlobalAutoRefresh, router, elementRef, widgetContextBinding) {
33105
33563
  this.dynamic = dynamic;
33106
33564
  this.translateService = translateService;
33107
33565
  this.route = route;
@@ -33109,6 +33567,7 @@ class WidgetsDashboardComponent {
33109
33567
  this.widgetGlobalAutoRefresh = widgetGlobalAutoRefresh;
33110
33568
  this.router = router;
33111
33569
  this.elementRef = elementRef;
33570
+ this.widgetContextBinding = widgetContextBinding;
33112
33571
  /**
33113
33572
  * Indicates if device info in config should be overridden with values from context property.
33114
33573
  */
@@ -33401,8 +33860,11 @@ class WidgetsDashboardComponent {
33401
33860
  return widgets;
33402
33861
  }
33403
33862
  if (this.isDeviceTypeDashboard) {
33863
+ // MTM-64730: this has to stay above executeResolvers, otherwise the resolvers check access to
33864
+ // the device originally configured in the widget and fail for users without permission to
33865
+ // read it.
33404
33866
  const keysToOverride = ['device', '__target'];
33405
- widgets.forEach(widget => (widget.config = this.replaceKeysWithContext(widget.config, keysToOverride)));
33867
+ await this.widgetContextBinding.applyContextToWidgets(widgets, this.context, widget => (widget.config = this.replaceKeysWithContext(widget.config, keysToOverride)));
33406
33868
  }
33407
33869
  const tuple = widgets.map(widget => ({
33408
33870
  componentId: widget.componentId || widget.name,
@@ -33449,7 +33911,7 @@ class WidgetsDashboardComponent {
33449
33911
  }
33450
33912
  return result;
33451
33913
  }
33452
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetsDashboardComponent, deps: [{ token: DynamicComponentService }, { token: i1$1.TranslateService }, { token: i1$3.ActivatedRoute }, { token: ModalService }, { token: WidgetGlobalAutoRefreshService }, { token: i1$3.Router }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
33914
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetsDashboardComponent, deps: [{ token: DynamicComponentService }, { token: i1$1.TranslateService }, { token: i1$3.ActivatedRoute }, { token: ModalService }, { token: WidgetGlobalAutoRefreshService }, { token: i1$3.Router }, { token: i0.ElementRef }, { token: WidgetContextBindingService }], target: i0.ɵɵFactoryTarget.Component }); }
33453
33915
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: WidgetsDashboardComponent, isStandalone: true, selector: "c8y-widgets-dashboard", inputs: { widgets: "widgets", context: "context", contextDashboard: "contextDashboard", _settings: ["settings", "_settings"], isCopyDisabled: "isCopyDisabled", breadcrumb: "breadcrumb", editModeButtons: "editModeButtons", isSaveDisabled: "isSaveDisabled", clearWidgetContentOnLeave: "clearWidgetContentOnLeave" }, outputs: { onAddWidget: "onAddWidget", onEditWidget: "onEditWidget", onDeleteWidget: "onDeleteWidget", onChangeDashboard: "onChangeDashboard", onResize: "onResize", onEditDashboard: "onEditDashboard", onCopyDashboard: "onCopyDashboard", onDeleteDashboard: "onDeleteDashboard", onChangeStart: "onChangeStart", onChangeEnd: "onChangeEnd", onSaveDashboard: "onSaveDashboard", onCancelDashboard: "onCancelDashboard", revertChange: "revertChange" }, host: { styleAttribute: "\n display: block;\n ", classAttribute: "dashboard c8y-grid-dashboard" }, providers: [WidgetsDashboardEventService], viewQueries: [{ propertyName: "dashboardChildren", predicate: DashboardChildComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (!!settings.title) {\n <c8y-title>\n @let dashboardTitle =\n settings.translateDashboardTitle ? (settings.title | translate) : settings.title;\n {{ dashboardTitle }}\n </c8y-title>\n}\n\n@if (!!breadcrumb) {\n <c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n </c8y-breadcrumb>\n}\n\n@if (!(editMode$ | async)) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n >\n <button\n class=\"btn btn-link animated fadeIn hidden-xs\"\n title=\"{{ 'Edit widgets' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isDisabled\"\n (click)=\"enableEditMode()\"\n data-cy=\"c8y-widget-dashboard--edit-widgets\"\n >\n <i c8yIcon=\"send-backward\"></i>\n <span class=\"m-l-4\">{{ 'Edit widgets' | translate }}</span>\n </button>\n <button\n class=\"btn btn-link visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"send-backward\"></i>\n <span class=\"m-l-4\">{{ 'Edit widgets' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (editMode$ | async) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n >\n <button\n class=\"btn btn-link animated fadeIn\"\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n itemClass=\"d-flex a-i-center gap-8\"\n >\n <div class=\"input-group input-group-sm animated fadeIn\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default btn-sm btn-icon\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"\n editModeButtons.undoButtonDisabled\n ? ''\n : (undoMessage\n | translate: { changeToUndo: editModeButtons.changeToUndoName | translate })\n \"\n container=\"body\"\n (click)=\"revertChange.emit('undo')\"\n [disabled]=\"editModeButtons.undoButtonDisabled\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default btn-sm btn-icon\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"\n editModeButtons.redoButtonDisabled\n ? ''\n : (redoMessage\n | translate: { changeToRedo: editModeButtons.changeToRedoName | translate })\n \"\n container=\"body\"\n (click)=\"revertChange.emit('redo')\"\n [disabled]=\"editModeButtons.redoButtonDisabled\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n </div>\n <span></span>\n </div>\n <div class=\"btn-group animated fadeIn\">\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancelDashboardSave()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary btn-sm m-l-8\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n [disabled]=\"editModeButtons.undoButtonDisabled && isSaveDisabled\"\n (click)=\"saveDashboard()\"\n data-cy=\"c8y-widgets-dashboard--save\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </c8y-action-bar-item>\n}\n\n@if (onEditDashboard.observers.length) {\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link hidden-xs m-l-0\"\n title=\"{{ 'Dashboard settings' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isDisabled || (editMode$ | async)\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"c8y-widgets-dashboard--edit-dashboard\"\n >\n <i c8yIcon=\"sorting-slider\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Dashboard settings' | translate }}\n </span>\n </button>\n <button\n class=\"btn btn-link visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"sorting-slider\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Dashboard settings' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.allowFullscreen) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"-5000\"\n itemClass=\"pull-right\"\n >\n <button\n class=\"btn btn-link\"\n [attr.aria-label]=\"'Full screen' | translate\"\n tooltip=\"{{ 'Full screen' | translate }}\"\n placement=\"left\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"toggleFullscreen()\"\n data-cy=\"widgets-dashboard--Full-screen\"\n >\n <i [c8yIcon]=\"(inFullScreen$ | async) ? 'compress' : 'expand'\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visibile-lg-inline\">\n {{ 'Full screen' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.canCopy) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <div class=\"d-flex a-i-center p-r-16\">\n <button\n class=\"hidden-xs\"\n title=\"{{\n (isCopyDisabled === true || !isCopyDisabled?.state ? 'Disabled' : copyDashboardLabel)\n | translate\n }}\"\n type=\"button\"\n [ngClass]=\"{ 'btn btn-link': !settings.canDelete }\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"onCopyDashboard.emit()\"\n [disabled]=\"isCopyDisabled === true || !isCopyDisabled?.state || (editMode$ | async)\"\n >\n <i c8yIcon=\"clone\"></i>\n <span>{{ copyDashboardLabel | translate }}</span>\n </button>\n @if (!isCopyDisabled?.state && copyDisabledPopoverMsg) {\n <button\n class=\"btn-help btn-help--sm hidden-xs flex-no-shrink\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"copyDisabledPopoverMsg | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"false\"\n data-cy=\"widgets-dashboard--info-copy-dashboard\"\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\n ></button>\n }\n </div>\n <button\n class=\"visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [ngClass]=\"{ 'btn btn-link': !settings.canDelete }\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"clone\"></i>\n <span>{{ copyDashboardLabel | translate }}</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.canDelete && onDeleteDashboard.observers.length) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n >\n <button\n class=\"hidden-xs\"\n title=\"{{ 'Delete`dashboard`' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--delete-dashboard\"\n [ngClass]=\"{ 'btn btn-link': !settings.canCopy }\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isDisabled || (editMode$ | async)\"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Delete`dashboard`</span>\n </button>\n <button\n class=\"visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--delete-dashboard-mobile\"\n [ngClass]=\"{ 'btn btn-link': !settings.canCopy }\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Delete`dashboard`</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (!(isLoadingWidgets$ | async)) {\n @if (resolvedWidgets$ | async; as widgetsToDisplay) {\n <!-- empty state -->\n @if (widgetsToDisplay?.length === 0) {\n <c8y-ui-empty-state\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n @if (onAddWidget.observers.length) {\n <div>\n @if (editMode$ | async) {\n <p translate>Add widgets to this dashboard.</p>\n }\n @if (!(editMode$ | async)) {\n <p translate>Click \"Edit widgets\" to unlock</p>\n }\n <div>\n @if (!settings.isDisabled && (editMode$ | async)) {\n <button\n class=\"btn btn-primary m-t-16\"\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"c8y-widgets-dashboard--add-widget\"\n translate\n >\n Add widget\n </button>\n }\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/cockpit/working-with-dashboards\">user documentation</a>.\n </small>\n </p>\n </div>\n }\n </c8y-ui-empty-state>\n }\n\n <c8y-dashboard\n [columns]=\"settings.columns\"\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n [layout]=\"settings.layout\"\n [rows]=\"settings.rows\"\n [alignViewHeight]=\"settings.alignViewHeight\"\n [float]=\"settings.float\"\n [gap]=\"settings.widgetMargin\"\n #dashboard\n >\n @for (widget of widgetsToDisplay; track widget.id || widget.name || $index) {\n <c8y-dashboard-child\n [class]=\"widget.classes\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || scaledDefaultWidth\"\n [height]=\"widget._height || scaledDefaultHeight\"\n [minW]=\"widget._minW || scaledDefaultMinWidth\"\n [minH]=\"widget._minH || scaledDefaultMinHeight\"\n [margin]=\"settings.widgetMargin\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n [editMode]=\"editMode$ | async\"\n (changeStart)=\"\n onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\n \"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (toggleFullscreen)=\"toggleFullscreenOnWidget(child)\"\n [canToggleFullscreen]=\"!(inFullScreen$ | async) || widgetInFullscreenMode\"\n #child\n >\n @let widgetTitle =\n widget.title | translate: { noTranslateRemoveContext: !settings.translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span data-cy=\"c8y-dashboard-list--device-widget\">\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n @if (onEditWidget.observers.length) {\n <c8y-dashboard-child-action>\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--Edit-widget\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n }\n @if (onDeleteWidget.observers.length) {\n <c8y-dashboard-child-action>\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n data-cy=\"c8y-widgets-dashboard--remove-widget\"\n (click)=\"\n onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\n \"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n }\n\n @if (child.intersected) {\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n }\n </c8y-dashboard-child>\n }\n </c8y-dashboard>\n }\n} @else {\n <c8y-loading class=\"col-xs-12 text-center\"></c8y-loading>\n}\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$4.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "directive", type: i1$8.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "progressLabel", "message"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "component", type: GuideDocsComponent, selector: "[c8y-guide-docs]" }, { kind: "directive", type: GuideHrefDirective, selector: "[c8y-guide-href]", inputs: ["c8y-guide-href"] }, { kind: "component", type: DashboardComponent, selector: "c8y-dashboard", inputs: ["columns", "layout", "alignViewHeight", "float", "gap", "minH", "minW", "rows"], outputs: ["dashboardChange"] }, { kind: "component", type: DashboardChildComponent, selector: "c8y-dashboard-child", inputs: ["x", "y", "width", "height", "minH", "minW", "data", "margin", "useIntersection", "isFrozen", "canToggleFullscreen", "editMode", "class"], outputs: ["changeStart", "changeEnd", "toggleFullscreen"] }, { kind: "component", type: DashboardChildTitleComponent, selector: "c8y-dashboard-child-title" }, { kind: "component", type: DashboardChildActionComponent, selector: "c8y-dashboard-child-action" }, { kind: "component", type: DynamicComponentComponent, selector: "c8y-dynamic-component", inputs: ["componentId", "config", "mode", "notFoundError", "executeResolvers"], outputs: ["updateWidgetClasses"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
33454
33916
  }
33455
33917
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: WidgetsDashboardComponent, decorators: [{
@@ -33483,7 +33945,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
33483
33945
  C8yTranslatePipe,
33484
33946
  AsyncPipe
33485
33947
  ], changeDetection: ChangeDetectionStrategy.Eager, template: "@if (!!settings.title) {\n <c8y-title>\n @let dashboardTitle =\n settings.translateDashboardTitle ? (settings.title | translate) : settings.title;\n {{ dashboardTitle }}\n </c8y-title>\n}\n\n@if (!!breadcrumb) {\n <c8y-breadcrumb>\n <c8y-breadcrumb-item\n [icon]=\"breadcrumb.icon\"\n [label]=\"breadcrumb.label\"\n [path]=\"breadcrumb.path\"\n ></c8y-breadcrumb-item>\n </c8y-breadcrumb>\n}\n\n@if (!(editMode$ | async)) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n >\n <button\n class=\"btn btn-link animated fadeIn hidden-xs\"\n title=\"{{ 'Edit widgets' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isDisabled\"\n (click)=\"enableEditMode()\"\n data-cy=\"c8y-widget-dashboard--edit-widgets\"\n >\n <i c8yIcon=\"send-backward\"></i>\n <span class=\"m-l-4\">{{ 'Edit widgets' | translate }}</span>\n </button>\n <button\n class=\"btn btn-link visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"send-backward\"></i>\n <span class=\"m-l-4\">{{ 'Edit widgets' | translate }}</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (editMode$ | async) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n >\n <button\n class=\"btn btn-link animated fadeIn\"\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"widget-dashboard--Add-widget\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add widget' | translate }}\n </button>\n </c8y-action-bar-item>\n\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"ACTION_BAR_EDIT_WIDGETS_PRIORITY\"\n itemClass=\"d-flex a-i-center gap-8\"\n >\n <div class=\"input-group input-group-sm animated fadeIn\">\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default btn-sm btn-icon\"\n [attr.aria-label]=\"'Undo' | translate\"\n [tooltip]=\"\n editModeButtons.undoButtonDisabled\n ? ''\n : (undoMessage\n | translate: { changeToUndo: editModeButtons.changeToUndoName | translate })\n \"\n container=\"body\"\n (click)=\"revertChange.emit('undo')\"\n [disabled]=\"editModeButtons.undoButtonDisabled\"\n >\n <i [c8yIcon]=\"'undo'\"></i>\n </button>\n </div>\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default btn-sm btn-icon\"\n [attr.aria-label]=\"'Redo' | translate\"\n [tooltip]=\"\n editModeButtons.redoButtonDisabled\n ? ''\n : (redoMessage\n | translate: { changeToRedo: editModeButtons.changeToRedoName | translate })\n \"\n container=\"body\"\n (click)=\"revertChange.emit('redo')\"\n [disabled]=\"editModeButtons.redoButtonDisabled\"\n >\n <i [c8yIcon]=\"'redo'\"></i>\n </button>\n </div>\n <span></span>\n </div>\n <div class=\"btn-group animated fadeIn\">\n <button\n class=\"btn btn-default btn-sm\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"cancelDashboardSave()\"\n >\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary btn-sm m-l-8\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n [disabled]=\"editModeButtons.undoButtonDisabled && isSaveDisabled\"\n (click)=\"saveDashboard()\"\n data-cy=\"c8y-widgets-dashboard--save\"\n >\n {{ 'Save' | translate }}\n </button>\n </div>\n </c8y-action-bar-item>\n}\n\n@if (onEditDashboard.observers.length) {\n <c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link hidden-xs m-l-0\"\n title=\"{{ 'Dashboard settings' | translate }}\"\n type=\"button\"\n [disabled]=\"settings.isDisabled || (editMode$ | async)\"\n (click)=\"onEditDashboard.emit()\"\n data-cy=\"c8y-widgets-dashboard--edit-dashboard\"\n >\n <i c8yIcon=\"sorting-slider\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Dashboard settings' | translate }}\n </span>\n </button>\n <button\n class=\"btn btn-link visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"sorting-slider\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visible-lg-inline\">\n {{ 'Dashboard settings' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.allowFullscreen) {\n <c8y-action-bar-item\n [placement]=\"'right'\"\n [priority]=\"-5000\"\n itemClass=\"pull-right\"\n >\n <button\n class=\"btn btn-link\"\n [attr.aria-label]=\"'Full screen' | translate\"\n tooltip=\"{{ 'Full screen' | translate }}\"\n placement=\"left\"\n container=\"body\"\n type=\"button\"\n [delay]=\"500\"\n (click)=\"toggleFullscreen()\"\n data-cy=\"widgets-dashboard--Full-screen\"\n >\n <i [c8yIcon]=\"(inFullScreen$ | async) ? 'compress' : 'expand'\"></i>\n <span class=\"visible-xs-inline hidden-sm visible-md-inline visibile-lg-inline\">\n {{ 'Full screen' | translate }}\n </span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.canCopy) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-2000\"\n >\n <div class=\"d-flex a-i-center p-r-16\">\n <button\n class=\"hidden-xs\"\n title=\"{{\n (isCopyDisabled === true || !isCopyDisabled?.state ? 'Disabled' : copyDashboardLabel)\n | translate\n }}\"\n type=\"button\"\n [ngClass]=\"{ 'btn btn-link': !settings.canDelete }\"\n data-cy=\"widgets-dashboard--copy-dashboard\"\n (click)=\"onCopyDashboard.emit()\"\n [disabled]=\"isCopyDisabled === true || !isCopyDisabled?.state || (editMode$ | async)\"\n >\n <i c8yIcon=\"clone\"></i>\n <span>{{ copyDashboardLabel | translate }}</span>\n </button>\n @if (!isCopyDisabled?.state && copyDisabledPopoverMsg) {\n <button\n class=\"btn-help btn-help--sm hidden-xs flex-no-shrink\"\n [attr.aria-label]=\"'Help' | translate\"\n [popover]=\"copyDisabledPopoverMsg | translate\"\n placement=\"top\"\n triggers=\"focus\"\n container=\"body\"\n type=\"button\"\n [adaptivePosition]=\"false\"\n data-cy=\"widgets-dashboard--info-copy-dashboard\"\n (click)=\"$event.preventDefault(); $event.stopPropagation()\"\n ></button>\n }\n </div>\n <button\n class=\"visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n [ngClass]=\"{ 'btn btn-link': !settings.canDelete }\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"clone\"></i>\n <span>{{ copyDashboardLabel | translate }}</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (settings.canDelete && onDeleteDashboard.observers.length) {\n <c8y-action-bar-item\n [placement]=\"'more'\"\n [priority]=\"-3000\"\n >\n <button\n class=\"hidden-xs\"\n title=\"{{ 'Delete`dashboard`' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--delete-dashboard\"\n [ngClass]=\"{ 'btn btn-link': !settings.canCopy }\"\n (click)=\"onDeleteDashboard.emit()\"\n [disabled]=\"settings.isDisabled || (editMode$ | async)\"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Delete`dashboard`</span>\n </button>\n <button\n class=\"visible-xs m-l-0\"\n tooltip=\"{{ 'Not available on mobile phone' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--delete-dashboard-mobile\"\n [ngClass]=\"{ 'btn btn-link': !settings.canCopy }\"\n [disabled]=\"true\"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Delete`dashboard`</span>\n </button>\n </c8y-action-bar-item>\n}\n\n@if (!(isLoadingWidgets$ | async)) {\n @if (resolvedWidgets$ | async; as widgetsToDisplay) {\n <!-- empty state -->\n @if (widgetsToDisplay?.length === 0) {\n <c8y-ui-empty-state\n [icon]=\"'c8y-device'\"\n [title]=\"'No widgets to display.' | translate\"\n >\n @if (onAddWidget.observers.length) {\n <div>\n @if (editMode$ | async) {\n <p translate>Add widgets to this dashboard.</p>\n }\n @if (!(editMode$ | async)) {\n <p translate>Click \"Edit widgets\" to unlock</p>\n }\n <div>\n @if (!settings.isDisabled && (editMode$ | async)) {\n <button\n class=\"btn btn-primary m-t-16\"\n title=\"{{ 'Add widget' | translate }}\"\n type=\"button\"\n (click)=\"onAddWidget.emit()\"\n data-cy=\"c8y-widgets-dashboard--add-widget\"\n translate\n >\n Add widget\n </button>\n }\n </div>\n <p c8y-guide-docs>\n <small\n translate\n ngNonBindable\n >\n Find out more in the\n <a c8y-guide-href=\"/docs/cockpit/working-with-dashboards\">user documentation</a>.\n </small>\n </p>\n </div>\n }\n </c8y-ui-empty-state>\n }\n\n <c8y-dashboard\n [columns]=\"settings.columns\"\n (dashboardChange)=\"onChangeDashboard.emit($event)\"\n [layout]=\"settings.layout\"\n [rows]=\"settings.rows\"\n [alignViewHeight]=\"settings.alignViewHeight\"\n [float]=\"settings.float\"\n [gap]=\"settings.widgetMargin\"\n #dashboard\n >\n @for (widget of widgetsToDisplay; track widget.id || widget.name || $index) {\n <c8y-dashboard-child\n [class]=\"widget.classes\"\n [x]=\"widget._x\"\n [y]=\"widget._y\"\n [width]=\"widget._width || scaledDefaultWidth\"\n [height]=\"widget._height || scaledDefaultHeight\"\n [minW]=\"widget._minW || scaledDefaultMinWidth\"\n [minH]=\"widget._minH || scaledDefaultMinHeight\"\n [margin]=\"settings.widgetMargin\"\n [data]=\"widget\"\n [useIntersection]=\"true\"\n [editMode]=\"editMode$ | async\"\n (changeStart)=\"\n onChangeStart.emit({ widget: widget, source: child, dashboard: dashboard })\n \"\n (changeEnd)=\"onChangeEnd.emit({ widget: widget, source: child, dashboard: dashboard })\"\n (toggleFullscreen)=\"toggleFullscreenOnWidget(child)\"\n [canToggleFullscreen]=\"!(inFullScreen$ | async) || widgetInFullscreenMode\"\n #child\n >\n @let widgetTitle =\n widget.title | translate: { noTranslateRemoveContext: !settings.translateWidgetTitle };\n <c8y-dashboard-child-title [attr.title]=\"widgetTitle\">\n <span data-cy=\"c8y-dashboard-list--device-widget\">\n {{ widgetTitle }}\n </span>\n </c8y-dashboard-child-title>\n @if (onEditWidget.observers.length) {\n <c8y-dashboard-child-action>\n <button\n title=\"{{ 'Edit widget' | translate }}\"\n type=\"button\"\n data-cy=\"widgets-dashboard--Edit-widget\"\n (click)=\"onEditWidget.emit({ widget: widget, source: child, dashboard: dashboard })\"\n >\n <i c8yIcon=\"pencil\"></i>\n <span translate>Edit</span>\n </button>\n </c8y-dashboard-child-action>\n }\n @if (onDeleteWidget.observers.length) {\n <c8y-dashboard-child-action>\n <button\n title=\"{{ 'Remove widget' | translate }}\"\n type=\"button\"\n data-cy=\"c8y-widgets-dashboard--remove-widget\"\n (click)=\"\n onDeleteWidget.emit({ widget: widget, source: child, dashboard: dashboard })\n \"\n >\n <i c8yIcon=\"delete\"></i>\n <span translate>Remove</span>\n </button>\n </c8y-dashboard-child-action>\n }\n\n @if (child.intersected) {\n <c8y-dynamic-component\n [componentId]=\"widget.componentId || widget.name\"\n [config]=\"\n widget.templateUrl || widget.widgetComponent\n ? { child: widget, dashboard: contextDashboard, context: context }\n : widget.config\n \"\n (updateWidgetClasses)=\"updateWidgetClasses(widget, $event)\"\n ></c8y-dynamic-component>\n }\n </c8y-dashboard-child>\n }\n </c8y-dashboard>\n }\n} @else {\n <c8y-loading class=\"col-xs-12 text-center\"></c8y-loading>\n}\n" }]
33486
- }], ctorParameters: () => [{ type: DynamicComponentService }, { type: i1$1.TranslateService }, { type: i1$3.ActivatedRoute }, { type: ModalService }, { type: WidgetGlobalAutoRefreshService }, { type: i1$3.Router }, { type: i0.ElementRef }], propDecorators: { widgets: [{
33948
+ }], ctorParameters: () => [{ type: DynamicComponentService }, { type: i1$1.TranslateService }, { type: i1$3.ActivatedRoute }, { type: ModalService }, { type: WidgetGlobalAutoRefreshService }, { type: i1$3.Router }, { type: i0.ElementRef }, { type: WidgetContextBindingService }], propDecorators: { widgets: [{
33487
33949
  type: Input
33488
33950
  }], context: [{
33489
33951
  type: Input
@@ -37613,7 +38075,7 @@ class SelectModalComponent {
37613
38075
  provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
37614
38076
  useExisting: forwardRef(() => SelectModalComponent)
37615
38077
  }
37616
- ], usesOnChanges: true, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"icon\"></i>\n <h1\n class=\"h3\"\n id=\"modal-title\"\n >\n {{ title | translate }}\n </h1>\n </div>\n <div class=\"p-16 text-center separator-bottom min-height-fit\">\n <p class=\"m-b-8\">{{ subTitle | translate }}</p>\n <div class=\"row\">\n <div\n *ngIf=\"showFilter\"\n [ngClass]=\"{\n 'col-xs-6': showFilter && additionalFilterTemplate,\n 'col-xs-12': !showFilter || !additionalFilterTemplate\n }\"\n >\n <c8y-filter\n [icon]=\"'search'\"\n (onSearch)=\"updatePipe($event)\"\n ></c8y-filter>\n </div>\n <div\n *ngIf=\"additionalFilterTemplate\"\n [ngClass]=\"{\n 'col-xs-6': showFilter && additionalFilterTemplate,\n 'col-xs-12': !showFilter || !additionalFilterTemplate\n }\"\n >\n <ng-container *ngTemplateOutlet=\"additionalFilterTemplate\"></ng-container>\n </div>\n </div>\n </div>\n <div\n class=\"modal-inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-l-16 p-r-16\">\n <div\n class=\"panel m-t-8 m-b-8\"\n *ngIf=\"!items || items.length === 0 || (emptyItemsOnly && hideEmptyItems)\"\n >\n <div class=\"c8y-empty-state text-left\">\n <h1\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"{{ icon }} \"\n ></h1>\n <p>{{ (noItemsMessage | translate) ?? 'No items to display.' | translate }}</p>\n </div>\n </div>\n </div>\n <c8y-list-group>\n <ng-container *ngFor=\"let item of listItems | selectModalFilterPipe : filterTerm\">\n <c8y-li *ngIf=\"item.options?.length > 0 || !hideEmptyItems\">\n <c8y-li-icon>\n <i c8yIcon=\"{{ icon }}\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-30\">\n <div class=\"col-9\">\n <div\n *ngFor=\"let bodyPart of item.body\"\n [ngClass]=\"bodyPart.class\"\n >\n <c8y-highlight\n [title]=\"bodyPart.value\"\n [pattern]=\"filterTerm\"\n [text]=\"bodyPart.value\"\n ></c8y-highlight>\n </div>\n </div>\n\n <div\n class=\"col-3 text-right\"\n *ngIf=\"item.additionalInformation\"\n >\n <div [ngClass]=\"item.additionalInformation.class\">\n {{ item.additionalInformation.value }}\n </div>\n </div>\n </c8y-li-body>\n\n <c8y-li-collapse *ngIf=\"item.options?.length > 0\">\n <c8y-list-group>\n <c8y-li *ngFor=\"let option of item.options\">\n <c8y-li-radio\n [name]=\"mode === 'single' ? 'single' : item.groupId\"\n (onSelect)=\"updateChoice({ item: item, id: option.obj.id })\"\n [disabled]=\"option.disabled\"\n [selected]=\"option.selected\"\n ></c8y-li-radio>\n <c8y-li-body class=\"content-flex-20\">\n <div\n *ngFor=\"let optionPart of option.body; let i = index\"\n [ngClass]=\"optionPart.class\"\n >\n <c8y-highlight\n [pattern]=\"filterTerm\"\n [text]=\"optionPart.value\"\n ></c8y-highlight>\n </div>\n <ng-container\n *ngIf=\"option.template\"\n [ngTemplateOutlet]=\"option.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item, option: option }\"\n ></ng-container>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\n </c8y-li>\n </ng-container>\n <div *ngIf=\"areMoreEntries\">\n <div\n class=\"alert alert-info m-t-16 m-r-8 m-l-8\"\n translate\n >\n Some entries might not be shown. Try narrowing search criteria.\n </div>\n </div>\n </c8y-list-group>\n </div>\n\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n data-cy=\"select-modal--Cancel-button\"\n *ngIf=\"labels.cancel\"\n (click)=\"dismiss()\"\n c8yProductExperience\n inherit\n [actionData]=\"{ result: labels.cancel }\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n data-cy=\"select-modal--Save-button\"\n (click)=\"select()\"\n [disabled]=\"!selected\"\n c8yProductExperience\n inherit\n [actionData]=\"{ result: labels.ok }\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FilterInputComponent, selector: "c8y-filter", inputs: ["icon", "filterTerm"], outputs: ["onSearch"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: SelectModalFilterPipe, name: "selectModalFilterPipe" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
38078
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"viewport-modal\">\n <div class=\"modal-header dialog-header\">\n <i [c8yIcon]=\"icon\"></i>\n <h1\n class=\"h3\"\n id=\"modal-title\"\n >\n {{ title | translate }}\n </h1>\n </div>\n <div class=\"p-16 text-center separator-bottom min-height-fit\">\n <p class=\"m-b-8\">{{ subTitle | translate }}</p>\n <div class=\"row\">\n <div\n *ngIf=\"showFilter\"\n [ngClass]=\"{\n 'col-xs-6': showFilter && additionalFilterTemplate,\n 'col-xs-12': !showFilter || !additionalFilterTemplate\n }\"\n >\n <c8y-filter\n [icon]=\"'search'\"\n (onSearch)=\"updatePipe($event)\"\n ></c8y-filter>\n </div>\n <div\n *ngIf=\"additionalFilterTemplate\"\n [ngClass]=\"{\n 'col-xs-6': showFilter && additionalFilterTemplate,\n 'col-xs-12': !showFilter || !additionalFilterTemplate\n }\"\n >\n <ng-container *ngTemplateOutlet=\"additionalFilterTemplate\"></ng-container>\n </div>\n </div>\n </div>\n <div\n class=\"modal-inner-scroll\"\n id=\"modal-body\"\n >\n <div class=\"p-l-16 p-r-16\">\n <div\n class=\"panel m-t-8 m-b-8\"\n *ngIf=\"!items || items.length === 0 || (emptyItemsOnly && hideEmptyItems)\"\n >\n <div class=\"c8y-empty-state text-left\">\n <h1\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"{{ icon }} \"\n ></h1>\n <p>{{ (noItemsMessage | translate) ?? 'No items to display.' | translate }}</p>\n </div>\n </div>\n </div>\n <c8y-list-group>\n <ng-container *ngFor=\"let item of listItems | selectModalFilterPipe : filterTerm\">\n <c8y-li *ngIf=\"item.options?.length > 0 || !hideEmptyItems\">\n <c8y-li-icon>\n <i c8yIcon=\"{{ icon }}\"></i>\n </c8y-li-icon>\n\n <c8y-li-body class=\"content-flex-30\">\n <div class=\"col-9\">\n <div\n *ngFor=\"let bodyPart of item.body\"\n [ngClass]=\"bodyPart.class\"\n >\n <c8y-highlight\n [title]=\"bodyPart.value\"\n [pattern]=\"filterTerm\"\n [text]=\"bodyPart.value\"\n ></c8y-highlight>\n </div>\n </div>\n\n <div\n class=\"col-3 text-right\"\n *ngIf=\"item.additionalInformation\"\n >\n <div [ngClass]=\"item.additionalInformation.class\">\n {{ item.additionalInformation.value }}\n </div>\n </div>\n </c8y-li-body>\n\n <c8y-li-collapse *ngIf=\"item.options?.length > 0\">\n <c8y-list-group>\n <c8y-li *ngFor=\"let option of item.options\">\n <c8y-li-radio\n [name]=\"mode === 'single' ? 'single' : item.groupId\"\n (onSelect)=\"updateChoice({ item: item, id: option.obj.id })\"\n [disabled]=\"option.disabled\"\n [selected]=\"option.selected\"\n ></c8y-li-radio>\n <c8y-li-body class=\"content-flex-20\">\n <div\n *ngFor=\"let optionPart of option.body; let i = index\"\n [ngClass]=\"optionPart.class\"\n >\n <c8y-highlight\n [pattern]=\"filterTerm\"\n [text]=\"optionPart.value\"\n ></c8y-highlight>\n </div>\n <ng-container\n *ngIf=\"option.template\"\n [ngTemplateOutlet]=\"option.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item, option: option }\"\n ></ng-container>\n </c8y-li-body>\n </c8y-li>\n </c8y-list-group>\n </c8y-li-collapse>\n </c8y-li>\n </ng-container>\n <div *ngIf=\"areMoreEntries\">\n <div\n class=\"alert alert-info m-t-16 m-r-8 m-l-8\"\n translate\n >\n Some entries might not be shown. Try narrowing search criteria.\n </div>\n </div>\n </c8y-list-group>\n </div>\n\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ labels.cancel | translate }}\"\n type=\"button\"\n data-cy=\"select-modal--Cancel-button\"\n *ngIf=\"labels.cancel\"\n (click)=\"dismiss()\"\n c8yProductExperience\n inherit\n [actionData]=\"{ result: labels.cancel }\"\n >\n {{ labels.cancel | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ labels.ok | translate }}\"\n type=\"button\"\n data-cy=\"select-modal--Save-button\"\n (click)=\"select()\"\n [disabled]=\"!selected\"\n c8yProductExperience\n inherit\n [actionData]=\"{ result: labels.ok }\"\n >\n {{ labels.ok | translate }}\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FilterInputComponent, selector: "c8y-filter", inputs: ["icon", "filterTerm"], outputs: ["onSearch"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable", "selectOnClick"], outputs: ["collapsedChange"] }, { kind: "component", type: ListItemIconComponent, selector: "c8y-list-item-icon, c8y-li-icon", inputs: ["icon", "status"] }, { kind: "component", type: ListItemBodyComponent, selector: "c8y-list-item-body, c8y-li-body", inputs: ["body"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "component", type: ListItemCollapseComponent, selector: "c8y-list-item-collapse, c8y-li-collapse", inputs: ["collapseWay"] }, { kind: "component", type: ListItemRadioComponent, selector: "c8y-list-item-radio, c8y-li-radio", inputs: ["selected", "name", "disabled", "value"], outputs: ["onSelect"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: SelectModalFilterPipe, name: "selectModalFilterPipe" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
37617
38079
  }
37618
38080
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: SelectModalComponent, decorators: [{
37619
38081
  type: Component,
@@ -39671,7 +40133,7 @@ class ProviderConfigurationComponent {
39671
40133
  return mapValues(configuration, value => (value === '<<Encrypted>>' ? undefined : value));
39672
40134
  }
39673
40135
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ProviderConfigurationComponent, deps: [{ token: Permissions }, { token: i1$3.ActivatedRoute }, { token: ModalService }, { token: AlertService }, { token: ProviderDefinitionsService }, { token: ProviderConfigurationService }, { token: C8yJSONSchema }], target: i0.ɵɵFactoryTarget.Component }); }
39674
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: ProviderConfigurationComponent, isStandalone: true, selector: "c8y-sms-gateway", providers: [ProviderConfigurationService, ProviderDefinitionsService], ngImport: i0, template: "<c8y-title>\n {{ (layout$ | async)?.pageTitle | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [label]=\"'Settings' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle !='Connectivity'\"\n [label]=\"'SMS provider' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle =='Connectivity'\"\n [label]=\"'Connectivity' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle =='Connectivity'\"\n [icon]=\"'cog'\"\n [label]=\"'SIM provider settings' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"row\">\n <div class=\"col-md-8 col-xs-12\">\n <form class=\"card card--fullpage\" (ngSubmit)=\"saveProviderConfiguration()\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ (layout$ | async)?.cardTitle | translate }}\n </div>\n </div>\n <div class=\"inner-scroll\">\n <div class=\"card-block\">\n <p *ngIf=\"!!(layout$ | async)?.description\" class=\"m-b-8\">\n {{ (layout$ | async)?.description | translate }}\n </p>\n <c8y-form-group>\n <label for=\"providerName\">{{ (layout$ | async)?.providerName | translate }}</label>\n <c8y-typeahead\n [disabled]=\"!permissions.hasAllRoles((layout$ | async)?.saveRoles || [])\"\n [ngModel]=\"selectedProvider$ | async\"\n [displayProperty]=\"'displayName'\"\n name=\"providerName\"\n placeholder=\"{{ (layout$ | async)?.providerNamePlaceholder | translate }}\"\n (onSearch)=\"providerInput$.next($event)\"\n [allowFreeEntries]=\"false\"\n [required]=\"true\"\n [container]=\"'body'\"\n >\n <c8y-li\n *ngFor=\"let provider of providers$ | async\"\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n (click)=\"changeProvider$.next(provider); providerInput$.next('')\"\n [active]=\"(selectedProvider$ | async) === provider\"\n [attr.role]=\"'menuitem'\"\n >\n <c8y-highlight\n [text]=\"provider.displayName || '--'\"\n [pattern]=\"providerInput$ | async\"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages>\n <c8y-message\n name=\"notExisting\"\n [text]=\"(layout$ | async)?.providerNameNoMatchesHint | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n <formly-form\n *ngIf=\"selectedProvider$ | async\"\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n ></formly-form>\n </div>\n </div>\n <div class=\"card-footer separator\" *c8yIfAllowed=\"allRoles$ | async; allowAny\">\n <button\n *c8yIfAllowed=\"(layout$ | async)?.deleteRoles\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"deleteProviderConfiguration()\"\n [disabled]=\"\n !(configuration$ | async)?.provider && !(configuration$ | async)?.providerName\n \"\n title=\"{{ (layout$ | async)?.deleteBtnLabel | translate }}\"\n >\n {{ (layout$ | async)?.deleteBtnLabel | translate }}\n </button>\n <button\n *c8yIfAllowed=\"(layout$ | async)?.saveRoles\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"form.invalid || form.pristine\"\n title=\"{{ (layout$ | async)?.saveBtnLabel | translate }}\"\n >\n {{ (layout$ | async)?.saveBtnLabel | translate }}\n </button>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable"], outputs: ["collapsedChange"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "directive", type: MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$5.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "directive", type: IfAllowedDirective, selector: "[c8yIfAllowed]", inputs: ["c8yIfAllowed", "c8yIfAllowedAllowAny"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
40136
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: ProviderConfigurationComponent, isStandalone: true, selector: "c8y-sms-gateway", providers: [ProviderConfigurationService, ProviderDefinitionsService], ngImport: i0, template: "<c8y-title>\n {{ (layout$ | async)?.pageTitle | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n [label]=\"'Settings' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle !='Connectivity'\"\n [label]=\"'SMS provider' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle =='Connectivity'\"\n [label]=\"'Connectivity' | translate\"\n [icon]=\"'cog'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item *ngIf=\"(layout$ | async)?.pageTitle =='Connectivity'\"\n [icon]=\"'cog'\"\n [label]=\"'SIM provider settings' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<div class=\"row\">\n <div class=\"col-md-8 col-xs-12\">\n <form class=\"card card--fullpage\" (ngSubmit)=\"saveProviderConfiguration()\">\n <div class=\"card-header separator\">\n <div class=\"card-title\">\n {{ (layout$ | async)?.cardTitle | translate }}\n </div>\n </div>\n <div class=\"inner-scroll\">\n <div class=\"card-block\">\n <p *ngIf=\"!!(layout$ | async)?.description\" class=\"m-b-8\">\n {{ (layout$ | async)?.description | translate }}\n </p>\n <c8y-form-group>\n <label for=\"providerName\">{{ (layout$ | async)?.providerName | translate }}</label>\n <c8y-typeahead\n [disabled]=\"!permissions.hasAllRoles((layout$ | async)?.saveRoles || [])\"\n [ngModel]=\"selectedProvider$ | async\"\n [displayProperty]=\"'displayName'\"\n name=\"providerName\"\n placeholder=\"{{ (layout$ | async)?.providerNamePlaceholder | translate }}\"\n (onSearch)=\"providerInput$.next($event)\"\n [allowFreeEntries]=\"false\"\n [required]=\"true\"\n [container]=\"'body'\"\n >\n <c8y-li\n *ngFor=\"let provider of providers$ | async\"\n class=\"p-l-8 p-r-8 c8y-list__item--link\"\n (click)=\"changeProvider$.next(provider); providerInput$.next('')\"\n [active]=\"(selectedProvider$ | async) === provider\"\n [attr.role]=\"'menuitem'\"\n >\n <c8y-highlight\n [text]=\"provider.displayName || '--'\"\n [pattern]=\"providerInput$ | async\"\n ></c8y-highlight>\n </c8y-li>\n </c8y-typeahead>\n <c8y-messages>\n <c8y-message\n name=\"notExisting\"\n [text]=\"(layout$ | async)?.providerNameNoMatchesHint | translate\"\n ></c8y-message>\n </c8y-messages>\n </c8y-form-group>\n <formly-form\n *ngIf=\"selectedProvider$ | async\"\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n [options]=\"options\"\n ></formly-form>\n </div>\n </div>\n <div class=\"card-footer separator\" *c8yIfAllowed=\"allRoles$ | async; allowAny\">\n <button\n *c8yIfAllowed=\"(layout$ | async)?.deleteRoles\"\n class=\"btn btn-default\"\n type=\"button\"\n (click)=\"deleteProviderConfiguration()\"\n [disabled]=\"\n !(configuration$ | async)?.provider && !(configuration$ | async)?.providerName\n \"\n title=\"{{ (layout$ | async)?.deleteBtnLabel | translate }}\"\n >\n {{ (layout$ | async)?.deleteBtnLabel | translate }}\n </button>\n <button\n *c8yIfAllowed=\"(layout$ | async)?.saveRoles\"\n class=\"btn btn-primary\"\n type=\"submit\"\n [disabled]=\"form.invalid || form.pristine\"\n title=\"{{ (layout$ | async)?.saveBtnLabel | translate }}\"\n >\n {{ (layout$ | async)?.saveBtnLabel | translate }}\n </button>\n </div>\n </form>\n </div>\n</div>\n", dependencies: [{ kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule$1 }, { kind: "directive", type: i1$7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1$7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: TypeaheadComponent, selector: "c8y-typeahead", inputs: ["required", "maxlength", "disabled", "allowFreeEntries", "placeholder", "displayProperty", "icon", "name", "autoClose", "hideNew", "container", "selected", "title", "ariaLabel", "ariaLabelledby", "highlightFirstItem"], outputs: ["onSearch", "onIconClick"] }, { kind: "component", type: HighlightComponent, selector: "c8y-highlight", inputs: ["pattern", "text", "elementClass", "shouldTrimPattern"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ListItemComponent, selector: "c8y-list-item, c8y-li", inputs: ["active", "highlighted", "emptyActions", "dense", "collapsed", "selectable", "selectOnClick"], outputs: ["collapsedChange"] }, { kind: "component", type: MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage", "additionalMessages"] }, { kind: "directive", type: MessageDirective, selector: "c8y-message", inputs: ["name", "text"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i2$5.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "directive", type: IfAllowedDirective, selector: "[c8yIfAllowed]", inputs: ["c8yIfAllowed", "c8yIfAllowedAllowAny"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
39675
40137
  }
39676
40138
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: ProviderConfigurationComponent, decorators: [{
39677
40139
  type: Component,
@@ -41746,5 +42208,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
41746
42208
  * Generated bundle index. Do not edit.
41747
42209
  */
41748
42210
 
41749
- export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AUTO_AGGREGATION_ICON, AUTO_POINTS_TOOLTIP, AUTO_POINTS_TOOLTIP_KEPT, 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, ApplyRangeClassPipe, AssetDefinitionsService, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BASELINE_COLUMNS, BASELINE_ROWS, 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, DatapointDescriptionPipe, DatapointLabelPipe, DatapointLibraryValidationErrors, DatapointSyncService, DatapointUnitPipe, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DropdownFocusTrapDirective, 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_SKIP_APP_KEY_HEADER, 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, InputGroupEditableComponent, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntersectionObserverService, 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, LoadingMessageComponent, 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, PasswordValidationDirective, PasswordValidationService, 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, RELOAD_QUERY_PARAM, 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, VirtualScrollListenerDirective, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetActionWrapperComponent, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, buildDatapointLabel, buildDatapointTranslationKey, 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, isBinaryFile, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideSkipAppKeyHeader, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, runGuardsOnParamsOrReloadChange, scaleWidgetDimensions, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, translateDatapointDescription, translateDatapointLabel, translateDatapointText, translateDatapointUnit, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
42211
+ export { ACTIONS_STEPPER, AGGREGATIONS, AGGREGATION_ICONS, AGGREGATION_LABELS, AGGREGATION_LIMITS, AGGREGATION_TEXTS, AGGREGATION_VALUES, AGGREGATION_VALUES_ARR, ARRAY_VALIDATION_PREFIX, ASSET_PATH, AUTO_AGGREGATION_ICON, AUTO_POINTS_TOOLTIP, AUTO_POINTS_TOOLTIP_KEPT, 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, ApplyRangeClassPipe, AssetDefinitionsService, AssetHierarchyService, AssetLinkPipe, AssetPropertyService, AssetTypesRealtimeService, AssetTypesService, AuditLogComponent, AuditLogModule, AuthenticationModule, BASELINE_COLUMNS, BASELINE_ROWS, 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, DatapointDescriptionPipe, DatapointLabelPipe, DatapointLibraryValidationErrors, DatapointSyncService, DatapointUnitPipe, DateContextQueryParamNames, DateFilterMapper, DateFormatService, DatePickerComponent, DatePickerModule, DatePipe, DateTimePickerComponent, DateTimePickerModule, DefaultValidationDirective, DeviceBootstrapRealtimeService, DeviceService, DeviceStatusComponent, DeviceStatusModule, DismissAlertStrategy, DocsModule, DocsService, DrawerModule, DrawerOutletComponent, DrawerService, DropAreaComponent, DropAreaModule, DropdownDirectionDirective, DropdownFocusTrapDirective, 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_SKIP_APP_KEY_HEADER, 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, InputGroupEditableComponent, InputGroupListComponent, InputGroupListContainerDirective, InterAppService, IntersectionObserverService, 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, ListItemSelectionControl, ListItemSelectionControlDirective, ListItemSelectionHost, ListItemTimelineComponent, LoadMoreComponent, LoadingComponent, LoadingMessageComponent, 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, PasswordValidationDirective, PasswordValidationService, 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, RELOAD_QUERY_PARAM, 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, VirtualScrollListenerDirective, VirtualScrollWindowDirective, VirtualScrollWindowStrategy, VirtualScrollerWrapperComponent, VisibleControlsPipe, WIDGET_CONFIGURATION_GRID_SIZE, WIDGET_TYPE_VALUES, WILDCARD_SEARCH_FEATURE_KEY, WebSDKVersionFactory, WidgetActionWrapperComponent, WidgetContextBindingService, WidgetGlobalAutoRefreshService, WidgetTimeContextActionBarPriority, WidgetTimeContextComponent, WidgetTimeContextDateRangeService, WidgetTimeContextMediatorService, WidgetsDashboardComponent, WidgetsDashboardEventService, WizardBodyComponent, WizardComponent, WizardFooterComponent, WizardHeaderComponent, WizardModalService, WizardModule, WizardOutletComponent, WizardService, ZipService, _virtualScrollWindowStrategyFactory, alertOnError, allEntriesAreEqual, asyncValidateArrayElements, buildDatapointLabel, buildDatapointTranslationKey, 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, isBinaryFile, isEagerDynamicComponents, isExtensionFactory, isLazyDynamicComponents, isPromise, languagesFactory, loadLocale, localeId, localePathFactory, memoize, minColumnGridTrackSize, operationStatusClasses, operationStatusIcons, provideBootstrapMetadata, provideCommonPipes, provideCommonServices, provideDefaultOptionsAppInitializer, provideI18n, provideLanguageSelectorAppInitializer, providePluginsLoaderServiceAppInitializer, provideSkipAppKeyHeader, provideTranslationServiceInstance, ratiosByColumnTypes, removeContextIndicators, removeDuplicatesIds, resolveInjectedFactories, retryWithDelay, runGuardsOnParamsOrReloadChange, scaleWidgetDimensions, simpleJsonPathValidator, sortByPriority, stateToFactory, statusAlert, statusClasses, statusIcons, throttle, toObservable, toObservableOfArrays, tooltips, translateDatapointDescription, translateDatapointLabel, translateDatapointText, translateDatapointUnit, trimTranslationKey, uniqueInCollectionByPathValidator, validateArrayElements, validateInternationalPhoneNumber, viewContextRoutes, wrapperLegendFieldConfig };
41750
42212
  //# sourceMappingURL=c8y-ngx-components.mjs.map