@mintplayer/ng-bootstrap 21.30.0 → 21.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/fesm2022/mintplayer-ng-bootstrap-a11y.mjs +455 -0
  2. package/fesm2022/mintplayer-ng-bootstrap-a11y.mjs.map +1 -0
  3. package/fesm2022/mintplayer-ng-bootstrap-accordion.mjs +8 -5
  4. package/fesm2022/mintplayer-ng-bootstrap-accordion.mjs.map +1 -1
  5. package/fesm2022/mintplayer-ng-bootstrap-breadcrumb.mjs +10 -4
  6. package/fesm2022/mintplayer-ng-bootstrap-breadcrumb.mjs.map +1 -1
  7. package/fesm2022/mintplayer-ng-bootstrap-button-group.mjs +7 -4
  8. package/fesm2022/mintplayer-ng-bootstrap-button-group.mjs.map +1 -1
  9. package/fesm2022/mintplayer-ng-bootstrap-calendar.mjs +131 -3
  10. package/fesm2022/mintplayer-ng-bootstrap-calendar.mjs.map +1 -1
  11. package/fesm2022/mintplayer-ng-bootstrap-carousel.mjs +80 -48
  12. package/fesm2022/mintplayer-ng-bootstrap-carousel.mjs.map +1 -1
  13. package/fesm2022/mintplayer-ng-bootstrap-code-snippet.mjs +4 -1
  14. package/fesm2022/mintplayer-ng-bootstrap-code-snippet.mjs.map +1 -1
  15. package/fesm2022/mintplayer-ng-bootstrap-color-picker.mjs +218 -14
  16. package/fesm2022/mintplayer-ng-bootstrap-color-picker.mjs.map +1 -1
  17. package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs +4 -3
  18. package/fesm2022/mintplayer-ng-bootstrap-datatable.mjs.map +1 -1
  19. package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs +2 -2
  20. package/fesm2022/mintplayer-ng-bootstrap-datepicker.mjs.map +1 -1
  21. package/fesm2022/mintplayer-ng-bootstrap-dock.mjs +294 -3
  22. package/fesm2022/mintplayer-ng-bootstrap-dock.mjs.map +1 -1
  23. package/fesm2022/mintplayer-ng-bootstrap-dropdown-menu.mjs +163 -18
  24. package/fesm2022/mintplayer-ng-bootstrap-dropdown-menu.mjs.map +1 -1
  25. package/fesm2022/mintplayer-ng-bootstrap-dropdown.mjs +179 -7
  26. package/fesm2022/mintplayer-ng-bootstrap-dropdown.mjs.map +1 -1
  27. package/fesm2022/mintplayer-ng-bootstrap-file-upload.mjs +14 -4
  28. package/fesm2022/mintplayer-ng-bootstrap-file-upload.mjs.map +1 -1
  29. package/fesm2022/mintplayer-ng-bootstrap-has-overlay.mjs +14 -0
  30. package/fesm2022/mintplayer-ng-bootstrap-has-overlay.mjs.map +1 -1
  31. package/fesm2022/mintplayer-ng-bootstrap-list-group.mjs +2 -1
  32. package/fesm2022/mintplayer-ng-bootstrap-list-group.mjs.map +1 -1
  33. package/fesm2022/mintplayer-ng-bootstrap-marquee.mjs +7 -4
  34. package/fesm2022/mintplayer-ng-bootstrap-marquee.mjs.map +1 -1
  35. package/fesm2022/mintplayer-ng-bootstrap-modal.mjs +70 -6
  36. package/fesm2022/mintplayer-ng-bootstrap-modal.mjs.map +1 -1
  37. package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs +5 -4
  38. package/fesm2022/mintplayer-ng-bootstrap-multiselect.mjs.map +1 -1
  39. package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs +6 -6
  40. package/fesm2022/mintplayer-ng-bootstrap-navbar-toggler.mjs.map +1 -1
  41. package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs +45 -13
  42. package/fesm2022/mintplayer-ng-bootstrap-navbar.mjs.map +1 -1
  43. package/fesm2022/mintplayer-ng-bootstrap-offcanvas.mjs +51 -5
  44. package/fesm2022/mintplayer-ng-bootstrap-offcanvas.mjs.map +1 -1
  45. package/fesm2022/mintplayer-ng-bootstrap-pagination.mjs +5 -3
  46. package/fesm2022/mintplayer-ng-bootstrap-pagination.mjs.map +1 -1
  47. package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs +18 -4
  48. package/fesm2022/mintplayer-ng-bootstrap-placeholder.mjs.map +1 -1
  49. package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs +6 -6
  50. package/fesm2022/mintplayer-ng-bootstrap-playlist-toggler.mjs.map +1 -1
  51. package/fesm2022/mintplayer-ng-bootstrap-popover.mjs +61 -6
  52. package/fesm2022/mintplayer-ng-bootstrap-popover.mjs.map +1 -1
  53. package/fesm2022/mintplayer-ng-bootstrap-priority-nav.mjs +19 -4
  54. package/fesm2022/mintplayer-ng-bootstrap-priority-nav.mjs.map +1 -1
  55. package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs +8 -5
  56. package/fesm2022/mintplayer-ng-bootstrap-progress-bar.mjs.map +1 -1
  57. package/fesm2022/mintplayer-ng-bootstrap-range.mjs +4 -3
  58. package/fesm2022/mintplayer-ng-bootstrap-range.mjs.map +1 -1
  59. package/fesm2022/mintplayer-ng-bootstrap-rating.mjs +34 -4
  60. package/fesm2022/mintplayer-ng-bootstrap-rating.mjs.map +1 -1
  61. package/fesm2022/mintplayer-ng-bootstrap-reduced-motion.mjs +59 -0
  62. package/fesm2022/mintplayer-ng-bootstrap-reduced-motion.mjs.map +1 -0
  63. package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs +91 -2
  64. package/fesm2022/mintplayer-ng-bootstrap-resizable.mjs.map +1 -1
  65. package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs +16 -5
  66. package/fesm2022/mintplayer-ng-bootstrap-scheduler.mjs.map +1 -1
  67. package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs +2 -2
  68. package/fesm2022/mintplayer-ng-bootstrap-scrollspy.mjs.map +1 -1
  69. package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs +28 -5
  70. package/fesm2022/mintplayer-ng-bootstrap-searchbox.mjs.map +1 -1
  71. package/fesm2022/mintplayer-ng-bootstrap-select.mjs +4 -3
  72. package/fesm2022/mintplayer-ng-bootstrap-select.mjs.map +1 -1
  73. package/fesm2022/mintplayer-ng-bootstrap-select2.mjs +18 -4
  74. package/fesm2022/mintplayer-ng-bootstrap-select2.mjs.map +1 -1
  75. package/fesm2022/mintplayer-ng-bootstrap-signature-pad.mjs +4 -3
  76. package/fesm2022/mintplayer-ng-bootstrap-signature-pad.mjs.map +1 -1
  77. package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs +2 -2
  78. package/fesm2022/mintplayer-ng-bootstrap-tab-control.mjs.map +1 -1
  79. package/fesm2022/mintplayer-ng-bootstrap-table.mjs +10 -3
  80. package/fesm2022/mintplayer-ng-bootstrap-table.mjs.map +1 -1
  81. package/fesm2022/mintplayer-ng-bootstrap-tile-manager.mjs +143 -29
  82. package/fesm2022/mintplayer-ng-bootstrap-tile-manager.mjs.map +1 -1
  83. package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs +2 -2
  84. package/fesm2022/mintplayer-ng-bootstrap-timepicker.mjs.map +1 -1
  85. package/fesm2022/mintplayer-ng-bootstrap-toast.mjs +7 -4
  86. package/fesm2022/mintplayer-ng-bootstrap-toast.mjs.map +1 -1
  87. package/fesm2022/mintplayer-ng-bootstrap-toggle-button.mjs +42 -21
  88. package/fesm2022/mintplayer-ng-bootstrap-toggle-button.mjs.map +1 -1
  89. package/fesm2022/mintplayer-ng-bootstrap-tooltip.mjs +33 -4
  90. package/fesm2022/mintplayer-ng-bootstrap-tooltip.mjs.map +1 -1
  91. package/fesm2022/mintplayer-ng-bootstrap-treeview.mjs +17 -7
  92. package/fesm2022/mintplayer-ng-bootstrap-treeview.mjs.map +1 -1
  93. package/fesm2022/mintplayer-ng-bootstrap-typeahead.mjs +50 -8
  94. package/fesm2022/mintplayer-ng-bootstrap-typeahead.mjs.map +1 -1
  95. package/fesm2022/mintplayer-ng-bootstrap-virtual-datatable.mjs +34 -12
  96. package/fesm2022/mintplayer-ng-bootstrap-virtual-datatable.mjs.map +1 -1
  97. package/fesm2022/mintplayer-ng-bootstrap-web-components-a11y.mjs +74 -0
  98. package/fesm2022/mintplayer-ng-bootstrap-web-components-a11y.mjs.map +1 -0
  99. package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler.mjs +1476 -71
  100. package/fesm2022/mintplayer-ng-bootstrap-web-components-scheduler.mjs.map +1 -1
  101. package/fesm2022/mintplayer-ng-bootstrap-web-components-splitter.mjs +194 -2
  102. package/fesm2022/mintplayer-ng-bootstrap-web-components-splitter.mjs.map +1 -1
  103. package/fesm2022/mintplayer-ng-bootstrap-web-components-tab-control.mjs +4 -0
  104. package/fesm2022/mintplayer-ng-bootstrap-web-components-tab-control.mjs.map +1 -1
  105. package/package.json +14 -2
  106. package/types/mintplayer-ng-bootstrap-a11y.d.ts +196 -0
  107. package/types/mintplayer-ng-bootstrap-accordion.d.ts +4 -2
  108. package/types/mintplayer-ng-bootstrap-breadcrumb.d.ts +2 -1
  109. package/types/mintplayer-ng-bootstrap-button-group.d.ts +2 -1
  110. package/types/mintplayer-ng-bootstrap-calendar.d.ts +32 -0
  111. package/types/mintplayer-ng-bootstrap-carousel.d.ts +56 -3
  112. package/types/mintplayer-ng-bootstrap-code-snippet.d.ts +1 -0
  113. package/types/mintplayer-ng-bootstrap-color-picker.d.ts +75 -4
  114. package/types/mintplayer-ng-bootstrap-datatable.d.ts +1 -1
  115. package/types/mintplayer-ng-bootstrap-dock.d.ts +51 -0
  116. package/types/mintplayer-ng-bootstrap-dropdown-menu.d.ts +54 -9
  117. package/types/mintplayer-ng-bootstrap-dropdown.d.ts +57 -2
  118. package/types/mintplayer-ng-bootstrap-file-upload.d.ts +4 -1
  119. package/types/mintplayer-ng-bootstrap-has-overlay.d.ts +14 -0
  120. package/types/mintplayer-ng-bootstrap-marquee.d.ts +2 -1
  121. package/types/mintplayer-ng-bootstrap-modal.d.ts +25 -1
  122. package/types/mintplayer-ng-bootstrap-multiselect.d.ts +2 -1
  123. package/types/mintplayer-ng-bootstrap-navbar-toggler.d.ts +4 -2
  124. package/types/mintplayer-ng-bootstrap-navbar.d.ts +25 -1
  125. package/types/mintplayer-ng-bootstrap-offcanvas.d.ts +23 -1
  126. package/types/mintplayer-ng-bootstrap-pagination.d.ts +3 -1
  127. package/types/mintplayer-ng-bootstrap-placeholder.d.ts +5 -1
  128. package/types/mintplayer-ng-bootstrap-playlist-toggler.d.ts +4 -2
  129. package/types/mintplayer-ng-bootstrap-popover.d.ts +21 -1
  130. package/types/mintplayer-ng-bootstrap-priority-nav.d.ts +4 -1
  131. package/types/mintplayer-ng-bootstrap-progress-bar.d.ts +4 -2
  132. package/types/mintplayer-ng-bootstrap-range.d.ts +2 -1
  133. package/types/mintplayer-ng-bootstrap-rating.d.ts +3 -0
  134. package/types/mintplayer-ng-bootstrap-reduced-motion.d.ts +36 -0
  135. package/types/mintplayer-ng-bootstrap-resizable.d.ts +4 -0
  136. package/types/mintplayer-ng-bootstrap-scheduler.d.ts +42 -9
  137. package/types/mintplayer-ng-bootstrap-scrollspy.d.ts +1 -1
  138. package/types/mintplayer-ng-bootstrap-searchbox.d.ts +8 -1
  139. package/types/mintplayer-ng-bootstrap-select.d.ts +2 -1
  140. package/types/mintplayer-ng-bootstrap-select2.d.ts +3 -0
  141. package/types/mintplayer-ng-bootstrap-signature-pad.d.ts +2 -1
  142. package/types/mintplayer-ng-bootstrap-table.d.ts +8 -1
  143. package/types/mintplayer-ng-bootstrap-tile-manager.d.ts +21 -2
  144. package/types/mintplayer-ng-bootstrap-toast.d.ts +6 -1
  145. package/types/mintplayer-ng-bootstrap-toggle-button.d.ts +11 -0
  146. package/types/mintplayer-ng-bootstrap-tooltip.d.ts +5 -0
  147. package/types/mintplayer-ng-bootstrap-treeview.d.ts +12 -1
  148. package/types/mintplayer-ng-bootstrap-typeahead.d.ts +11 -3
  149. package/types/mintplayer-ng-bootstrap-virtual-datatable.d.ts +14 -1
  150. package/types/mintplayer-ng-bootstrap-web-components-a11y.d.ts +34 -0
  151. package/types/mintplayer-ng-bootstrap-web-components-scheduler-core.d.ts +35 -11
  152. package/types/mintplayer-ng-bootstrap-web-components-scheduler.d.ts +246 -0
  153. package/types/mintplayer-ng-bootstrap-web-components-splitter.d.ts +95 -37
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-bootstrap-tooltip.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/tooltip/src/providers/tooltip-content.provider.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/component/tooltip.component.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/component/tooltip.component.html","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/directive/tooltip.directive.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/index.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/mintplayer-ng-bootstrap-tooltip.ts"],"sourcesContent":["import { InjectionToken, TemplateRef } from \"@angular/core\";\n\nexport const TOOLTIP_CONTENT = new InjectionToken<TemplateRef<any>>('TooltipContent');","import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, TemplateRef } from '@angular/core';\nimport { FadeInOutAnimation } from '@mintplayer/ng-animations';\nimport { Position } from '@mintplayer/ng-bootstrap';\nimport { BsHasOverlayComponent } from '@mintplayer/ng-bootstrap/has-overlay';\nimport { TOOLTIP_CONTENT } from '../providers/tooltip-content.provider';\n\n@Component({\n selector: 'bs-tooltip',\n templateUrl: './tooltip.component.html',\n styleUrls: ['./tooltip.component.scss'],\n imports: [NgTemplateOutlet, BsHasOverlayComponent],\n animations: [FadeInOutAnimation],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.position-relative]': 'true',\n },\n})\nexport class BsTooltipComponent {\n template = inject<TemplateRef<any>>(TOOLTIP_CONTENT);\n\n position = input<Position>('bottom');\n\n positionClass = computed(() => `bs-tooltip-${this.position()}`);\n\n marginClass = computed(() => {\n switch (this.position()) {\n case 'start': return 'me-1';\n case 'end': return 'ms-1';\n case 'top': return 'mb-1';\n case 'bottom': return 'mt-1';\n }\n });\n}\n","<bs-has-overlay></bs-has-overlay>\n<div [@fadeInOut] class=\"tooltip position-absolute show\"\n [class]=\"[positionClass(), marginClass()]\"\n role=\"tooltip\">\n <div class=\"tooltip-arrow position-absolute\" aria-hidden=\"true\"></div>\n <div class=\"tooltip-inner\">\n <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n </div>\n</div>\n","import { ConnectedPosition, Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { Directive, ElementRef, Host, input, Injector, OnDestroy, SkipSelf, TemplateRef } from '@angular/core';\nimport { Position } from '@mintplayer/ng-bootstrap';\nimport { BsTooltipComponent } from '../component/tooltip.component';\nimport { TOOLTIP_CONTENT } from '../providers/tooltip-content.provider';\n\n@Directive({\n selector: '*[bsTooltip]',\n host: {\n '(window:blur)': 'onBlur()',\n },\n})\nexport class BsTooltipDirective implements OnDestroy {\n\n constructor(\n private overlay: Overlay,\n private templateRef: TemplateRef<any>,\n private parentInjector: Injector,\n @Host() @SkipSelf() private parent: ElementRef\n ) {\n this.injector = Injector.create({\n providers: [{ provide: TOOLTIP_CONTENT, useValue: this.templateRef }],\n parent: this.parentInjector\n });\n this.portal = new ComponentPortal(BsTooltipComponent, null, this.injector);\n\n parent.nativeElement.onmouseenter = () => {\n this.showTooltip();\n };\n parent.nativeElement.onmouseleave = () => {\n this.hideTooltip();\n }\n }\n\n readonly bsTooltip = input<Position>('bottom');\n\n private injector: Injector;\n private portal: ComponentPortal<any>;\n private overlayRef: OverlayRef | null = null;\n\n onBlur() {\n this.hideTooltip();\n }\n\n showTooltip() {\n const positions: ConnectedPosition[] = [];\n switch (this.bsTooltip()) {\n case 'bottom': {\n positions.push({\n originX: \"center\",\n originY: \"bottom\", //<--\n overlayX: \"center\",\n overlayY: \"top\"\n });\n } break;\n case 'top': {\n positions.push({\n originX: \"center\",\n originY: \"top\", //<--\n overlayX: \"center\",\n overlayY: \"bottom\"\n });\n } break;\n case 'start': {\n positions.push({\n originX: \"start\", //<--\n originY: \"center\",\n overlayX: \"end\",\n overlayY: \"center\",\n });\n } break;\n case 'end': {\n positions.push({\n originX: \"end\", //<--\n originY: \"center\",\n overlayX: \"start\",\n overlayY: \"center\"\n });\n } break;\n }\n\n this.overlayRef = this.overlay.create({\n scrollStrategy: this.overlay.scrollStrategies.reposition(),\n positionStrategy: this.overlay.position()\n .flexibleConnectedTo(this.parent)\n .withPositions(positions),\n });\n const component = this.overlayRef.attach<BsTooltipComponent>(this.portal);\n component.setInput('position', this.bsTooltip());\n }\n\n hideTooltip() {\n if (this.overlayRef) {\n this.overlayRef.detach();\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n }\n\n ngOnDestroy() {\n this.hideTooltip();\n }\n\n}\n","export * from './directive/tooltip.directive';\n// export * from './component/tooltip.component';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mintplayer-ng-bootstrap-tooltip.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/tooltip/src/providers/tooltip-content.provider.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/providers/tooltip-id.provider.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/component/tooltip.component.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/component/tooltip.component.html","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/directive/tooltip.directive.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/src/index.ts","../../../../libs/mintplayer-ng-bootstrap/tooltip/mintplayer-ng-bootstrap-tooltip.ts"],"sourcesContent":["import { InjectionToken, TemplateRef } from \"@angular/core\";\n\nexport const TOOLTIP_CONTENT = new InjectionToken<TemplateRef<any>>('TooltipContent');","import { InjectionToken } from '@angular/core';\n\n/** The dom id assigned to the rendered tooltip element so the trigger can point at it via aria-describedby. */\nexport const TOOLTIP_ID = new InjectionToken<string>('TOOLTIP_ID');\n","import { NgTemplateOutlet } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, TemplateRef } from '@angular/core';\nimport { FadeInOutAnimation } from '@mintplayer/ng-animations';\nimport { Position } from '@mintplayer/ng-bootstrap';\nimport { BsHasOverlayComponent } from '@mintplayer/ng-bootstrap/has-overlay';\nimport { TOOLTIP_CONTENT } from '../providers/tooltip-content.provider';\nimport { TOOLTIP_ID } from '../providers/tooltip-id.provider';\n\n@Component({\n selector: 'bs-tooltip',\n templateUrl: './tooltip.component.html',\n styleUrls: ['./tooltip.component.scss'],\n imports: [NgTemplateOutlet, BsHasOverlayComponent],\n animations: [FadeInOutAnimation],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.position-relative]': 'true',\n },\n})\nexport class BsTooltipComponent {\n template = inject<TemplateRef<any>>(TOOLTIP_CONTENT);\n tooltipId = inject(TOOLTIP_ID);\n\n position = input<Position>('bottom');\n\n positionClass = computed(() => `bs-tooltip-${this.position()}`);\n\n marginClass = computed(() => {\n switch (this.position()) {\n case 'start': return 'me-1';\n case 'end': return 'ms-1';\n case 'top': return 'mb-1';\n case 'bottom': return 'mt-1';\n }\n });\n}\n","<bs-has-overlay></bs-has-overlay>\n<div [@fadeInOut] class=\"tooltip position-absolute show\"\n [class]=\"[positionClass(), marginClass()]\"\n [id]=\"tooltipId\"\n role=\"tooltip\">\n <div class=\"tooltip-arrow position-absolute\" aria-hidden=\"true\"></div>\n <div class=\"tooltip-inner\">\n <ng-container *ngTemplateOutlet=\"template\"></ng-container>\n </div>\n</div>\n","import { ConnectedPosition, Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { Directive, ElementRef, Host, inject, input, Injector, OnDestroy, SkipSelf, TemplateRef } from '@angular/core';\nimport { Position } from '@mintplayer/ng-bootstrap';\nimport { BsIdService, BsOverlayStackService } from '@mintplayer/ng-bootstrap/a11y';\nimport { BsTooltipComponent } from '../component/tooltip.component';\nimport { TOOLTIP_CONTENT } from '../providers/tooltip-content.provider';\nimport { TOOLTIP_ID } from '../providers/tooltip-id.provider';\n\n@Directive({\n selector: '*[bsTooltip]',\n host: {\n '(window:blur)': 'onBlur()',\n '(document:keydown.escape)': 'onEscape()',\n },\n})\nexport class BsTooltipDirective implements OnDestroy {\n private ids = inject(BsIdService);\n private overlayStack = inject(BsOverlayStackService);\n private readonly tooltipId = this.ids.next('bs-tooltip');\n private stackToken: symbol | null = null;\n\n constructor(\n private overlay: Overlay,\n private templateRef: TemplateRef<any>,\n private parentInjector: Injector,\n @Host() @SkipSelf() private parent: ElementRef\n ) {\n this.injector = Injector.create({\n providers: [\n { provide: TOOLTIP_CONTENT, useValue: this.templateRef },\n { provide: TOOLTIP_ID, useValue: this.tooltipId },\n ],\n parent: this.parentInjector\n });\n this.portal = new ComponentPortal(BsTooltipComponent, null, this.injector);\n\n parent.nativeElement.onmouseenter = () => {\n this.showTooltip();\n };\n parent.nativeElement.onmouseleave = () => {\n this.hideTooltip();\n }\n }\n\n readonly bsTooltip = input<Position>('bottom');\n\n private injector: Injector;\n private portal: ComponentPortal<any>;\n private overlayRef: OverlayRef | null = null;\n\n onBlur() {\n this.hideTooltip();\n }\n\n onEscape() {\n if (this.stackToken !== null && this.overlayStack.isTop(this.stackToken)) {\n this.hideTooltip();\n }\n }\n\n showTooltip() {\n if (this.overlayRef) return;\n\n const positions: ConnectedPosition[] = [];\n switch (this.bsTooltip()) {\n case 'bottom': {\n positions.push({\n originX: \"center\",\n originY: \"bottom\", //<--\n overlayX: \"center\",\n overlayY: \"top\"\n });\n } break;\n case 'top': {\n positions.push({\n originX: \"center\",\n originY: \"top\", //<--\n overlayX: \"center\",\n overlayY: \"bottom\"\n });\n } break;\n case 'start': {\n positions.push({\n originX: \"start\", //<--\n originY: \"center\",\n overlayX: \"end\",\n overlayY: \"center\",\n });\n } break;\n case 'end': {\n positions.push({\n originX: \"end\", //<--\n originY: \"center\",\n overlayX: \"start\",\n overlayY: \"center\"\n });\n } break;\n }\n\n this.overlayRef = this.overlay.create({\n scrollStrategy: this.overlay.scrollStrategies.reposition(),\n positionStrategy: this.overlay.position()\n .flexibleConnectedTo(this.parent)\n .withPositions(positions),\n });\n const component = this.overlayRef.attach<BsTooltipComponent>(this.portal);\n component.setInput('position', this.bsTooltip());\n\n this.parent.nativeElement.setAttribute('aria-describedby', this.tooltipId);\n if (this.stackToken === null) {\n this.stackToken = this.overlayStack.push();\n }\n }\n\n hideTooltip() {\n if (this.overlayRef) {\n this.overlayRef.detach();\n this.overlayRef.dispose();\n this.overlayRef = null;\n }\n this.parent.nativeElement.removeAttribute('aria-describedby');\n if (this.stackToken !== null) {\n this.overlayStack.release(this.stackToken);\n this.stackToken = null;\n }\n }\n\n ngOnDestroy() {\n this.hideTooltip();\n }\n\n}\n","export * from './directive/tooltip.directive';\n// export * from './component/tooltip.component';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -10,26 +10,30 @@ class BsTreeviewComponent {
10
10
  this.level = computed(() => !this.parent ? 0 : this.parent.level() + 1, ...(ngDevMode ? [{ debugName: "level" }] : /* istanbul ignore next */ []));
11
11
  this.indentation = computed(() => this.level() * 30, ...(ngDevMode ? [{ debugName: "indentation" }] : /* istanbul ignore next */ []));
12
12
  this.isExpanded = model(!this.parent, ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
13
- // Roving tabindex: track which item is focused
13
+ /**
14
+ * Direct-child items of THIS tree (not descendants). Used to compute
15
+ * aria-setsize and aria-posinset for each item among its siblings.
16
+ */
14
17
  this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
18
+ /** Roving tabindex tracking — only stored on the root tree. */
15
19
  this.focusedItem = signal(null, ...(ngDevMode ? [{ debugName: "focusedItem" }] : /* istanbul ignore next */ []));
16
20
  }
17
21
  getRootTree() {
18
22
  return this.parent ? this.parent.getRootTree() : this;
19
23
  }
20
24
  registerItem(item) {
25
+ this.items.update((items) => [...items, item]);
26
+ // First item gets focus by default (root-level state)
21
27
  const root = this.getRootTree();
22
- root.items.update((items) => [...items, item]);
23
- // First item gets focus by default
24
28
  if (root.focusedItem() === null) {
25
29
  root.focusedItem.set(item);
26
30
  }
27
31
  }
28
32
  unregisterItem(item) {
33
+ this.items.update((items) => items.filter(i => i !== item));
29
34
  const root = this.getRootTree();
30
- root.items.update((items) => items.filter(i => i !== item));
31
35
  if (root.focusedItem() === item) {
32
- const remaining = root.items();
36
+ const remaining = this.items();
33
37
  root.focusedItem.set(remaining.length > 0 ? remaining[0] : null);
34
38
  }
35
39
  }
@@ -57,6 +61,12 @@ class BsTreeviewItemComponent {
57
61
  this.chevronRight = signal(undefined, ...(ngDevMode ? [{ debugName: "chevronRight" }] : /* istanbul ignore next */ []));
58
62
  // Roving tabindex: only the focused item has tabindex 0
59
63
  this.tabIndex = computed(() => this.parent.isFocusedItem(this) ? 0 : -1, ...(ngDevMode ? [{ debugName: "tabIndex" }] : /* istanbul ignore next */ []));
64
+ /** APG tree pattern: 1-based depth. Root tree has level=0; items inside it are level=1. */
65
+ this.ariaLevel = computed(() => this.parent.level() + 1, ...(ngDevMode ? [{ debugName: "ariaLevel" }] : /* istanbul ignore next */ []));
66
+ /** Total siblings at this level (within this immediate tree). */
67
+ this.ariaSetSize = computed(() => this.parent.items().length, ...(ngDevMode ? [{ debugName: "ariaSetSize" }] : /* istanbul ignore next */ []));
68
+ /** 1-based position within siblings. */
69
+ this.ariaPosInSet = computed(() => this.parent.items().indexOf(this) + 1, ...(ngDevMode ? [{ debugName: "ariaPosInSet" }] : /* istanbul ignore next */ []));
60
70
  import('bootstrap-icons/icons/chevron-right.svg').then((icon) => {
61
71
  this.chevronRight.set(this.sanitizer.bypassSecurityTrustHtml(icon.default));
62
72
  });
@@ -75,11 +85,11 @@ class BsTreeviewItemComponent {
75
85
  }
76
86
  }
77
87
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsTreeviewItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
78
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", type: BsTreeviewItemComponent, isStandalone: true, selector: "bs-treeview-item", queries: [{ propertyName: "childTree", first: true, predicate: BsTreeviewComponent, isSignal: true }], ngImport: i0, template: "<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n", styles: ["bs-list-group-item{margin-bottom:-1px}bs-icon{transition:transform .2s}bs-icon.open{transform:rotate(90deg)}\n"], dependencies: [{ kind: "component", type: BsListGroupItemComponent, selector: "bs-list-group-item" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
88
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.11", type: BsTreeviewItemComponent, isStandalone: true, selector: "bs-treeview-item", queries: [{ propertyName: "childTree", first: true, predicate: BsTreeviewComponent, isSignal: true }], ngImport: i0, template: "<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.aria-level]=\"ariaLevel()\"\n [attr.aria-setsize]=\"ariaSetSize()\"\n [attr.aria-posinset]=\"ariaPosInSet()\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n", styles: ["bs-list-group-item{margin-bottom:-1px}bs-icon{transition:transform .2s}bs-icon.open{transform:rotate(90deg)}\n"], dependencies: [{ kind: "component", type: BsListGroupItemComponent, selector: "bs-list-group-item" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
79
89
  }
80
90
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsTreeviewItemComponent, decorators: [{
81
91
  type: Component,
82
- args: [{ selector: 'bs-treeview-item', imports: [BsListGroupItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n", styles: ["bs-list-group-item{margin-bottom:-1px}bs-icon{transition:transform .2s}bs-icon.open{transform:rotate(90deg)}\n"] }]
92
+ args: [{ selector: 'bs-treeview-item', imports: [BsListGroupItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.aria-level]=\"ariaLevel()\"\n [attr.aria-setsize]=\"ariaSetSize()\"\n [attr.aria-posinset]=\"ariaPosInSet()\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n", styles: ["bs-list-group-item{margin-bottom:-1px}bs-icon{transition:transform .2s}bs-icon.open{transform:rotate(90deg)}\n"] }]
83
93
  }], ctorParameters: () => [], propDecorators: { childTree: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BsTreeviewComponent), { ...{ descendants: false }, isSignal: true }] }] } });
84
94
 
85
95
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-bootstrap-treeview.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview/treeview.component.ts","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview/treeview.component.html","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview-item/treeview-item.component.ts","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview-item/treeview-item.component.html","../../../../libs/mintplayer-ng-bootstrap/treeview/mintplayer-ng-bootstrap-treeview.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, model, signal } from '@angular/core';\nimport { SlideUpDownAnimation } from '@mintplayer/ng-animations';\nimport { BsListGroupComponent } from '@mintplayer/ng-bootstrap/list-group';\nimport type { BsTreeviewItemComponent } from '../treeview-item/treeview-item.component';\n\n@Component({\n selector: 'bs-treeview',\n templateUrl: './treeview.component.html',\n styleUrls: ['./treeview.component.scss'],\n imports: [BsListGroupComponent],\n animations: [SlideUpDownAnimation],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTreeviewComponent {\n\n private parent = inject(BsTreeviewComponent, { skipSelf: true, optional: true });\n\n level = computed<number>((): number => !this.parent ? 0 : this.parent.level() + 1);\n indentation = computed(() => this.level() * 30);\n isExpanded = model<boolean>(!this.parent);\n\n // Roving tabindex: track which item is focused\n private items = signal<BsTreeviewItemComponent[]>([]);\n focusedItem = signal<BsTreeviewItemComponent | null>(null);\n\n private getRootTree(): BsTreeviewComponent {\n return this.parent ? this.parent.getRootTree() : this;\n }\n\n registerItem(item: BsTreeviewItemComponent) {\n const root = this.getRootTree();\n root.items.update((items: BsTreeviewItemComponent[]) => [...items, item]);\n // First item gets focus by default\n if (root.focusedItem() === null) {\n root.focusedItem.set(item);\n }\n }\n\n unregisterItem(item: BsTreeviewItemComponent) {\n const root = this.getRootTree();\n root.items.update((items: BsTreeviewItemComponent[]) => items.filter(i => i !== item));\n if (root.focusedItem() === item) {\n const remaining = root.items();\n root.focusedItem.set(remaining.length > 0 ? remaining[0] : null);\n }\n }\n\n setFocusedItem(item: BsTreeviewItemComponent) {\n this.getRootTree().focusedItem.set(item);\n }\n\n isFocusedItem(item: BsTreeviewItemComponent): boolean {\n return this.getRootTree().focusedItem() === item;\n }\n}\n","<bs-list-group [@slideUpDown]=\"isExpanded()\" class=\"d-block overflow-y-hidden\" [attr.role]=\"level() === 0 ? 'tree' : 'group'\">\n <ng-content></ng-content>\n</bs-list-group>\n","/// <reference types=\"../types\" />\n\nimport { ChangeDetectionStrategy, Component, computed, contentChild, DestroyRef, inject, signal } from '@angular/core';\nimport { BsListGroupItemComponent } from '@mintplayer/ng-bootstrap/list-group';\nimport { BsTreeviewComponent } from '../treeview/treeview.component';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\n\n@Component({\n selector: 'bs-treeview-item',\n templateUrl: './treeview-item.component.html',\n styleUrls: ['./treeview-item.component.scss'],\n imports: [BsListGroupItemComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTreeviewItemComponent {\n\n readonly parent = inject(BsTreeviewComponent);\n private sanitizer = inject(DomSanitizer);\n private destroyRef = inject(DestroyRef);\n\n readonly childTree = contentChild(BsTreeviewComponent, { descendants: false });\n chevronRight = signal<SafeHtml | undefined>(undefined);\n\n // Roving tabindex: only the focused item has tabindex 0\n tabIndex = computed(() => this.parent.isFocusedItem(this) ? 0 : -1);\n\n constructor() {\n import('bootstrap-icons/icons/chevron-right.svg').then((icon) => {\n this.chevronRight.set(this.sanitizer.bypassSecurityTrustHtml(icon.default));\n });\n\n // Register this item with the tree\n this.parent.registerItem(this);\n this.destroyRef.onDestroy(() => {\n this.parent.unregisterItem(this);\n });\n }\n\n onClick(ev: MouseEvent) {\n // Set this item as focused when clicked\n this.parent.setFocusedItem(this);\n\n const childTree = this.childTree();\n if (childTree) {\n childTree.isExpanded.update(v => !v);\n }\n }\n}\n","<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mintplayer-ng-bootstrap-treeview.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview/treeview.component.ts","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview/treeview.component.html","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview-item/treeview-item.component.ts","../../../../libs/mintplayer-ng-bootstrap/treeview/src/treeview-item/treeview-item.component.html","../../../../libs/mintplayer-ng-bootstrap/treeview/mintplayer-ng-bootstrap-treeview.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, model, signal } from '@angular/core';\nimport { SlideUpDownAnimation } from '@mintplayer/ng-animations';\nimport { BsListGroupComponent } from '@mintplayer/ng-bootstrap/list-group';\nimport type { BsTreeviewItemComponent } from '../treeview-item/treeview-item.component';\n\n@Component({\n selector: 'bs-treeview',\n templateUrl: './treeview.component.html',\n styleUrls: ['./treeview.component.scss'],\n imports: [BsListGroupComponent],\n animations: [SlideUpDownAnimation],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTreeviewComponent {\n\n private parent = inject(BsTreeviewComponent, { skipSelf: true, optional: true });\n\n level = computed<number>((): number => !this.parent ? 0 : this.parent.level() + 1);\n indentation = computed(() => this.level() * 30);\n isExpanded = model<boolean>(!this.parent);\n\n /**\n * Direct-child items of THIS tree (not descendants). Used to compute\n * aria-setsize and aria-posinset for each item among its siblings.\n */\n items = signal<BsTreeviewItemComponent[]>([]);\n /** Roving tabindex tracking — only stored on the root tree. */\n focusedItem = signal<BsTreeviewItemComponent | null>(null);\n\n private getRootTree(): BsTreeviewComponent {\n return this.parent ? this.parent.getRootTree() : this;\n }\n\n registerItem(item: BsTreeviewItemComponent) {\n this.items.update((items: BsTreeviewItemComponent[]) => [...items, item]);\n // First item gets focus by default (root-level state)\n const root = this.getRootTree();\n if (root.focusedItem() === null) {\n root.focusedItem.set(item);\n }\n }\n\n unregisterItem(item: BsTreeviewItemComponent) {\n this.items.update((items: BsTreeviewItemComponent[]) => items.filter(i => i !== item));\n const root = this.getRootTree();\n if (root.focusedItem() === item) {\n const remaining = this.items();\n root.focusedItem.set(remaining.length > 0 ? remaining[0] : null);\n }\n }\n\n setFocusedItem(item: BsTreeviewItemComponent) {\n this.getRootTree().focusedItem.set(item);\n }\n\n isFocusedItem(item: BsTreeviewItemComponent): boolean {\n return this.getRootTree().focusedItem() === item;\n }\n}\n","<bs-list-group [@slideUpDown]=\"isExpanded()\" class=\"d-block overflow-y-hidden\" [attr.role]=\"level() === 0 ? 'tree' : 'group'\">\n <ng-content></ng-content>\n</bs-list-group>\n","/// <reference types=\"../types\" />\n\nimport { ChangeDetectionStrategy, Component, computed, contentChild, DestroyRef, inject, signal } from '@angular/core';\nimport { BsListGroupItemComponent } from '@mintplayer/ng-bootstrap/list-group';\nimport { BsTreeviewComponent } from '../treeview/treeview.component';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\n\n@Component({\n selector: 'bs-treeview-item',\n templateUrl: './treeview-item.component.html',\n styleUrls: ['./treeview-item.component.scss'],\n imports: [BsListGroupItemComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTreeviewItemComponent {\n\n readonly parent = inject(BsTreeviewComponent);\n private sanitizer = inject(DomSanitizer);\n private destroyRef = inject(DestroyRef);\n\n readonly childTree = contentChild(BsTreeviewComponent, { descendants: false });\n chevronRight = signal<SafeHtml | undefined>(undefined);\n\n // Roving tabindex: only the focused item has tabindex 0\n tabIndex = computed(() => this.parent.isFocusedItem(this) ? 0 : -1);\n\n /** APG tree pattern: 1-based depth. Root tree has level=0; items inside it are level=1. */\n ariaLevel = computed(() => this.parent.level() + 1);\n /** Total siblings at this level (within this immediate tree). */\n ariaSetSize = computed(() => this.parent.items().length);\n /** 1-based position within siblings. */\n ariaPosInSet = computed(() => this.parent.items().indexOf(this) + 1);\n\n constructor() {\n import('bootstrap-icons/icons/chevron-right.svg').then((icon) => {\n this.chevronRight.set(this.sanitizer.bypassSecurityTrustHtml(icon.default));\n });\n\n // Register this item with the tree\n this.parent.registerItem(this);\n this.destroyRef.onDestroy(() => {\n this.parent.unregisterItem(this);\n });\n }\n\n onClick(ev: MouseEvent) {\n // Set this item as focused when clicked\n this.parent.setFocusedItem(this);\n\n const childTree = this.childTree();\n if (childTree) {\n childTree.isExpanded.update(v => !v);\n }\n }\n}\n","<bs-list-group-item (click)=\"onClick($event)\"\n class=\"d-block cursor-pointer list-group-item-action\"\n role=\"treeitem\"\n [attr.aria-expanded]=\"childTree() ? childTree()!.isExpanded() : null\"\n [attr.aria-level]=\"ariaLevel()\"\n [attr.aria-setsize]=\"ariaSetSize()\"\n [attr.aria-posinset]=\"ariaPosInSet()\"\n [attr.tabindex]=\"tabIndex()\">\n <span [style.padding-left.px]=\"parent.indentation()\">\n <span [innerHTML]=\"chevronRight()\" [class.open]=\"childTree()?.isExpanded()\" [class.invisible]=\"!childTree()\" class=\"d-inline-block me-2\" aria-hidden=\"true\"></span>\n <ng-content></ng-content>\n </span>\n</bs-list-group-item>\n<ng-content select=\"bs-treeview\"></ng-content>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MAaa,mBAAmB,CAAA;AARhC,IAAA,WAAA,GAAA;AAUU,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAEhF,IAAA,CAAA,KAAK,GAAG,QAAQ,CAAS,MAAc,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,OAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;AAClF,QAAA,IAAA,CAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,kFAAC;QAC/C,IAAA,CAAA,UAAU,GAAG,KAAK,CAAU,CAAC,IAAI,CAAC,MAAM,iFAAC;AAEzC;;;AAGG;AACH,QAAA,IAAA,CAAA,KAAK,GAAG,MAAM,CAA4B,EAAE,4EAAC;;AAE7C,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAiC,IAAI,kFAAC;AA+B3D,IAAA;IA7BS,WAAW,GAAA;AACjB,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,IAAI;IACvD;AAEA,IAAA,YAAY,CAAC,IAA6B,EAAA;AACxC,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAgC,KAAK,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;;AAEzE,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;AAC/B,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;AAC/B,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B;IACF;AAEA,IAAA,cAAc,CAAC,IAA6B,EAAA;QAC1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAgC,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;AACtF,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;AAC/B,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;AAC/B,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE;YAC9B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QAClE;IACF;AAEA,IAAA,cAAc,CAAC,IAA6B,EAAA;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;IAC1C;AAEA,IAAA,aAAa,CAAC,IAA6B,EAAA;QACzC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,KAAK,IAAI;IAClD;+GA5CW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAnB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,uQCbhC,yLAGA,EAAA,MAAA,EAAA,CAAA,0BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDMY,oBAAoB,EAAA,QAAA,EAAA,eAAA,EAAA,CAAA,EAAA,UAAA,EAClB,CAAC,oBAAoB,CAAC,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAGvB,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAR/B,SAAS;+BACE,aAAa,EAAA,OAAA,EAGd,CAAC,oBAAoB,CAAC,EAAA,UAAA,EACnB,CAAC,oBAAoB,CAAC,EAAA,eAAA,EACjB,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,yLAAA,EAAA,MAAA,EAAA,CAAA,0BAAA,CAAA,EAAA;;;AEXjD;MAca,uBAAuB,CAAA;AAmBlC,IAAA,WAAA,GAAA;AAjBS,QAAA,IAAA,CAAA,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACrC,QAAA,IAAA,CAAA,SAAS,GAAG,MAAM,CAAC,YAAY,CAAC;AAChC,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAE9B,IAAA,CAAA,SAAS,GAAG,YAAY,CAAC,mBAAmB,iFAAI,WAAW,EAAE,KAAK,EAAA,CAAG;AAC9E,QAAA,IAAA,CAAA,YAAY,GAAG,MAAM,CAAuB,SAAS,mFAAC;;QAGtD,IAAA,CAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,UAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAC;;AAGnE,QAAA,IAAA,CAAA,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,gFAAC;;AAEnD,QAAA,IAAA,CAAA,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,kFAAC;;QAExD,IAAA,CAAA,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,mFAAC;QAGlE,OAAO,yCAAyC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAI;AAC9D,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7E,QAAA,CAAC,CAAC;;AAGF,QAAA,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;AAC9B,QAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;AAC7B,YAAA,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC;AAClC,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,OAAO,CAAC,EAAc,EAAA;;AAEpB,QAAA,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC;AAEhC,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE;QAClC,IAAI,SAAS,EAAE;AACb,YAAA,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC;IACF;+GAvCW,uBAAuB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAvB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAMA,mBAAmB,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECpBvD,quBAcA,wKDHY,wBAAwB,EAAA,QAAA,EAAA,oBAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAGvB,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAPnC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,WAGnB,CAAC,wBAAwB,CAAC,EAAA,eAAA,EAClB,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,quBAAA,EAAA,MAAA,EAAA,CAAA,gHAAA,CAAA,EAAA;AAQb,SAAA,CAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,UAAA,CAAA,MAAA,mBAAmB,CAAA,EAAA,EAAA,GAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AEpB/E;;AAEG;;;;"}
@@ -1,41 +1,62 @@
1
1
  import * as i0 from '@angular/core';
2
- import { model, input, signal, computed, viewChild, output, effect, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, model, input, signal, computed, viewChild, output, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import * as i1 from '@angular/forms';
4
4
  import { FormsModule } from '@angular/forms';
5
- import { BsDropdownDirective, BsDropdownMenuDirective } from '@mintplayer/ng-bootstrap/dropdown';
5
+ import { BsLiveAnnouncerService, BsRovingFocusDirective, BsRovingFocusItemDirective } from '@mintplayer/ng-bootstrap/a11y';
6
+ import { BsDropdownDirective, BsDropdownMenuDirective, BsComboboxDirective } from '@mintplayer/ng-bootstrap/dropdown';
6
7
  import { BsDropdownMenuComponent, BsDropdownItemComponent } from '@mintplayer/ng-bootstrap/dropdown-menu';
7
8
  import { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';
8
9
  import { BsHasOverlayComponent } from '@mintplayer/ng-bootstrap/has-overlay';
9
10
  import { BsProgressComponent } from '@mintplayer/ng-bootstrap/progress-bar';
10
11
 
11
- let typeaheadIdCounter = 0;
12
12
  class BsTypeaheadComponent {
13
13
  constructor() {
14
+ this.announcer = inject(BsLiveAnnouncerService);
14
15
  this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
15
- this.listboxId = `typeahead-listbox-${typeaheadIdCounter++}`;
16
16
  this.suggestions = input([], ...(ngDevMode ? [{ debugName: "suggestions" }] : /* istanbul ignore next */ []));
17
17
  this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
18
18
  this.showNoSuggestions = computed(() => this.suggestions().length === 0, ...(ngDevMode ? [{ debugName: "showNoSuggestions" }] : /* istanbul ignore next */ []));
19
19
  this.textbox = viewChild.required('textbox');
20
+ this.rovingFocus = viewChild(BsRovingFocusDirective, ...(ngDevMode ? [{ debugName: "rovingFocus" }] : /* istanbul ignore next */ []));
20
21
  this.searchterm = model('', ...(ngDevMode ? [{ debugName: "searchterm" }] : /* istanbul ignore next */ []));
21
22
  this.isLoadingText = input('Loading...', ...(ngDevMode ? [{ debugName: "isLoadingText" }] : /* istanbul ignore next */ []));
22
23
  this.noSuggestionsText = input('No suggestions found', ...(ngDevMode ? [{ debugName: "noSuggestionsText" }] : /* istanbul ignore next */ []));
24
+ this.resultsAnnouncementSingular = input('1 result found', ...(ngDevMode ? [{ debugName: "resultsAnnouncementSingular" }] : /* istanbul ignore next */ []));
25
+ this.resultsAnnouncementPlural = input((count) => `${count} results found`, ...(ngDevMode ? [{ debugName: "resultsAnnouncementPlural" }] : /* istanbul ignore next */ []));
23
26
  this.provideSuggestions = output();
24
27
  this.suggestionSelected = output();
25
28
  this.submitted = output();
29
+ this.requestInFlight = false;
26
30
  effect(() => {
27
31
  const suggestions = this.suggestions();
28
32
  if (suggestions) {
29
33
  this.isLoading.set(false);
34
+ if (this.requestInFlight) {
35
+ this.requestInFlight = false;
36
+ this.announceResults(suggestions.length);
37
+ }
30
38
  }
31
39
  });
32
40
  }
41
+ announceResults(count) {
42
+ if (count === 0) {
43
+ this.announcer.announce(this.noSuggestionsText());
44
+ }
45
+ else if (count === 1) {
46
+ this.announcer.announce(this.resultsAnnouncementSingular());
47
+ }
48
+ else {
49
+ this.announcer.announce(this.resultsAnnouncementPlural()(count));
50
+ }
51
+ }
33
52
  onProvideSuggestions(value) {
34
53
  this.searchterm.set(value);
35
54
  if (value === '') {
36
55
  this.isOpen.set(false);
56
+ this.requestInFlight = false;
37
57
  }
38
58
  else {
59
+ this.requestInFlight = true;
39
60
  this.isLoading.set(true);
40
61
  this.isOpen.set(true);
41
62
  this.provideSuggestions.emit(value);
@@ -46,7 +67,21 @@ class BsTypeaheadComponent {
46
67
  this.isOpen.set(false);
47
68
  this.suggestionSelected.emit(suggestion);
48
69
  }
49
- onSubmit() {
70
+ onActivate() {
71
+ const rf = this.rovingFocus();
72
+ if (!rf)
73
+ return;
74
+ const suggestion = this.suggestions()[rf.activeIndex()];
75
+ if (suggestion) {
76
+ this.suggestionClicked(suggestion);
77
+ }
78
+ }
79
+ onCancel() {
80
+ // dropdown was already closed by bsCombobox; no extra work needed
81
+ }
82
+ onSubmit(event) {
83
+ // Suppress browser form-submit; we own the Enter semantics here.
84
+ event?.preventDefault();
50
85
  this.isOpen.set(false);
51
86
  this.submitted.emit(this.searchterm());
52
87
  }
@@ -54,12 +89,19 @@ class BsTypeaheadComponent {
54
89
  this.textbox().nativeElement.focus();
55
90
  }
56
91
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsTypeaheadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
57
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BsTypeaheadComponent, isStandalone: true, selector: "bs-typeahead", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, searchterm: { classPropertyName: "searchterm", publicName: "searchterm", isSignal: true, isRequired: false, transformFunction: null }, isLoadingText: { classPropertyName: "isLoadingText", publicName: "isLoadingText", isSignal: true, isRequired: false, transformFunction: null }, noSuggestionsText: { classPropertyName: "noSuggestionsText", publicName: "noSuggestionsText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", searchterm: "searchtermChange", provideSuggestions: "provideSuggestions", suggestionSelected: "suggestionSelected", submitted: "submitted" }, viewQueries: [{ propertyName: "textbox", first: true, predicate: ["textbox"], descendants: true, isSignal: true }], ngImport: i0, template: "<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\" role=\"combobox\" [attr.aria-expanded]=\"isOpen()\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n (keyup.enter)=\"onSubmit()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu role=\"listbox\" [id]=\"listboxId\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item (click)=\"suggestionClicked(suggestion)\" role=\"option\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n", styles: ["bs-progress{margin-top:-8px;margin-bottom:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "directive", type: BsDropdownDirective, selector: "[bsDropdown]", inputs: ["hasBackdrop", "sameWidth", "closeOnClickOutside", "sameDropdownWidth", "isOpen"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsDropdownMenuDirective, selector: "[bsDropdownMenu]" }, { kind: "component", type: BsDropdownMenuComponent, selector: "bs-dropdown-menu", inputs: ["maxHeight"] }, { kind: "component", type: BsDropdownItemComponent, selector: "bs-dropdown-item", inputs: ["isSelected", "disabled"] }, { kind: "component", type: BsProgressComponent, selector: "bs-progress", inputs: ["height", "isIndeterminate"] }, { kind: "component", type: BsHasOverlayComponent, selector: "bs-has-overlay" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
92
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BsTypeaheadComponent, isStandalone: true, selector: "bs-typeahead", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, suggestions: { classPropertyName: "suggestions", publicName: "suggestions", isSignal: true, isRequired: false, transformFunction: null }, searchterm: { classPropertyName: "searchterm", publicName: "searchterm", isSignal: true, isRequired: false, transformFunction: null }, isLoadingText: { classPropertyName: "isLoadingText", publicName: "isLoadingText", isSignal: true, isRequired: false, transformFunction: null }, noSuggestionsText: { classPropertyName: "noSuggestionsText", publicName: "noSuggestionsText", isSignal: true, isRequired: false, transformFunction: null }, resultsAnnouncementSingular: { classPropertyName: "resultsAnnouncementSingular", publicName: "resultsAnnouncementSingular", isSignal: true, isRequired: false, transformFunction: null }, resultsAnnouncementPlural: { classPropertyName: "resultsAnnouncementPlural", publicName: "resultsAnnouncementPlural", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", searchterm: "searchtermChange", provideSuggestions: "provideSuggestions", suggestionSelected: "suggestionSelected", submitted: "submitted" }, viewQueries: [{ propertyName: "textbox", first: true, predicate: ["textbox"], descendants: true, isSignal: true }, { propertyName: "rovingFocus", first: true, predicate: BsRovingFocusDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown popupRole=\"listbox\" [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n bsCombobox\n (activate)=\"onActivate()\"\n (cancel)=\"onCancel()\"\n (keydown.enter)=\"onSubmit($event)\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu bsRovingFocus mode=\"activedescendant\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item bsRovingFocusItem (click)=\"suggestionClicked(suggestion)\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n", styles: ["bs-progress{margin-top:-8px;margin-bottom:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "directive", type: BsDropdownDirective, selector: "[bsDropdown]", inputs: ["hasBackdrop", "sameWidth", "closeOnClickOutside", "sameDropdownWidth", "isOpen", "popupRole"], outputs: ["isOpenChange"], exportAs: ["bsDropdown"] }, { kind: "directive", type: BsDropdownMenuDirective, selector: "[bsDropdownMenu]" }, { kind: "component", type: BsDropdownMenuComponent, selector: "bs-dropdown-menu", inputs: ["maxHeight"] }, { kind: "component", type: BsDropdownItemComponent, selector: "bs-dropdown-item", inputs: ["isSelected", "disabled"] }, { kind: "directive", type: BsComboboxDirective, selector: "input[bsCombobox]", inputs: ["bsComboboxAutocomplete", "activeDescendant"], outputs: ["navigate", "activate", "cancel"], exportAs: ["bsCombobox"] }, { kind: "directive", type: BsRovingFocusDirective, selector: "[bsRovingFocus]", inputs: ["orientation", "mode", "wrap"], exportAs: ["bsRovingFocus"] }, { kind: "directive", type: BsRovingFocusItemDirective, selector: "[bsRovingFocusItem]", inputs: ["disabled"], exportAs: ["bsRovingFocusItem"] }, { kind: "component", type: BsProgressComponent, selector: "bs-progress", inputs: ["height", "isIndeterminate", "ariaLabel"] }, { kind: "component", type: BsHasOverlayComponent, selector: "bs-has-overlay" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
58
93
  }
59
94
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsTypeaheadComponent, decorators: [{
60
95
  type: Component,
61
- args: [{ selector: 'bs-typeahead', imports: [FormsModule, BsFormComponent, BsFormControlDirective, BsDropdownDirective, BsDropdownMenuDirective, BsDropdownMenuComponent, BsDropdownItemComponent, BsProgressComponent, BsHasOverlayComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\" role=\"combobox\" [attr.aria-expanded]=\"isOpen()\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n (keyup.enter)=\"onSubmit()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu role=\"listbox\" [id]=\"listboxId\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item (click)=\"suggestionClicked(suggestion)\" role=\"option\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n", styles: ["bs-progress{margin-top:-8px;margin-bottom:6px}\n"] }]
62
- }], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], textbox: [{ type: i0.ViewChild, args: ['textbox', { isSignal: true }] }], searchterm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchterm", required: false }] }, { type: i0.Output, args: ["searchtermChange"] }], isLoadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoadingText", required: false }] }], noSuggestionsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSuggestionsText", required: false }] }], provideSuggestions: [{ type: i0.Output, args: ["provideSuggestions"] }], suggestionSelected: [{ type: i0.Output, args: ["suggestionSelected"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
96
+ args: [{ selector: 'bs-typeahead', imports: [
97
+ FormsModule,
98
+ BsFormComponent, BsFormControlDirective,
99
+ BsDropdownDirective, BsDropdownMenuDirective, BsDropdownMenuComponent, BsDropdownItemComponent,
100
+ BsComboboxDirective,
101
+ BsRovingFocusDirective, BsRovingFocusItemDirective,
102
+ BsProgressComponent, BsHasOverlayComponent,
103
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown popupRole=\"listbox\" [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n bsCombobox\n (activate)=\"onActivate()\"\n (cancel)=\"onCancel()\"\n (keydown.enter)=\"onSubmit($event)\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu bsRovingFocus mode=\"activedescendant\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item bsRovingFocusItem (click)=\"suggestionClicked(suggestion)\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n", styles: ["bs-progress{margin-top:-8px;margin-bottom:6px}\n"] }]
104
+ }], ctorParameters: () => [], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }], textbox: [{ type: i0.ViewChild, args: ['textbox', { isSignal: true }] }], rovingFocus: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BsRovingFocusDirective), { isSignal: true }] }], searchterm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchterm", required: false }] }, { type: i0.Output, args: ["searchtermChange"] }], isLoadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoadingText", required: false }] }], noSuggestionsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSuggestionsText", required: false }] }], resultsAnnouncementSingular: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultsAnnouncementSingular", required: false }] }], resultsAnnouncementPlural: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultsAnnouncementPlural", required: false }] }], provideSuggestions: [{ type: i0.Output, args: ["provideSuggestions"] }], suggestionSelected: [{ type: i0.Output, args: ["suggestionSelected"] }], submitted: [{ type: i0.Output, args: ["submitted"] }] } });
63
105
 
64
106
  /**
65
107
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-bootstrap-typeahead.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/typeahead/src/typeahead.component.ts","../../../../libs/mintplayer-ng-bootstrap/typeahead/src/typeahead.component.html","../../../../libs/mintplayer-ng-bootstrap/typeahead/mintplayer-ng-bootstrap-typeahead.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, input, model, output, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BsDropdownDirective, BsDropdownMenuDirective } from '@mintplayer/ng-bootstrap/dropdown';\nimport { BsDropdownMenuComponent, BsDropdownItemComponent } from '@mintplayer/ng-bootstrap/dropdown-menu';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsHasOverlayComponent } from '@mintplayer/ng-bootstrap/has-overlay';\nimport { BsProgressComponent } from '@mintplayer/ng-bootstrap/progress-bar';\n\nlet typeaheadIdCounter = 0;\n\n@Component({\n selector: 'bs-typeahead',\n templateUrl: './typeahead.component.html',\n styleUrls: ['./typeahead.component.scss'],\n imports: [FormsModule, BsFormComponent, BsFormControlDirective, BsDropdownDirective, BsDropdownMenuDirective, BsDropdownMenuComponent, BsDropdownItemComponent, BsProgressComponent, BsHasOverlayComponent],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTypeaheadComponent {\n\n isOpen = model(false);\n readonly listboxId = `typeahead-listbox-${typeaheadIdCounter++}`;\n\n suggestions = input<any[]>([]);\n isLoading = signal<boolean>(false);\n showNoSuggestions = computed(() => this.suggestions().length === 0);\n\n readonly textbox = viewChild.required<ElementRef<HTMLInputElement>>('textbox');\n searchterm = model('');\n isLoadingText = input('Loading...');\n noSuggestionsText = input('No suggestions found');\n provideSuggestions = output<string>();\n suggestionSelected = output<any>();\n submitted = output<string>();\n\n constructor() {\n effect(() => {\n const suggestions = this.suggestions();\n if (suggestions) {\n this.isLoading.set(false);\n }\n });\n }\n\n onProvideSuggestions(value: string) {\n this.searchterm.set(value);\n if (value === '') {\n this.isOpen.set(false);\n } else {\n this.isLoading.set(true);\n this.isOpen.set(true);\n this.provideSuggestions.emit(value);\n }\n }\n\n suggestionClicked(suggestion: any) {\n this.searchterm.set(suggestion.text);\n this.isOpen.set(false);\n this.suggestionSelected.emit(suggestion);\n }\n\n onSubmit() {\n this.isOpen.set(false);\n this.submitted.emit(this.searchterm());\n }\n\n public focus() {\n this.textbox().nativeElement.focus();\n }\n}\n","<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\" role=\"combobox\" [attr.aria-expanded]=\"isOpen()\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n (keyup.enter)=\"onSubmit()\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu role=\"listbox\" [id]=\"listboxId\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\" role=\"option\" aria-disabled=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item (click)=\"suggestionClicked(suggestion)\" role=\"option\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mintplayer-ng-bootstrap-typeahead.mjs","sources":["../../../../libs/mintplayer-ng-bootstrap/typeahead/src/typeahead.component.ts","../../../../libs/mintplayer-ng-bootstrap/typeahead/src/typeahead.component.html","../../../../libs/mintplayer-ng-bootstrap/typeahead/mintplayer-ng-bootstrap-typeahead.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, inject, input, model, output, signal, viewChild } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { BsLiveAnnouncerService, BsRovingFocusDirective, BsRovingFocusItemDirective } from '@mintplayer/ng-bootstrap/a11y';\nimport { BsComboboxDirective, BsDropdownDirective, BsDropdownMenuDirective } from '@mintplayer/ng-bootstrap/dropdown';\nimport { BsDropdownMenuComponent, BsDropdownItemComponent } from '@mintplayer/ng-bootstrap/dropdown-menu';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsHasOverlayComponent } from '@mintplayer/ng-bootstrap/has-overlay';\nimport { BsProgressComponent } from '@mintplayer/ng-bootstrap/progress-bar';\n\n@Component({\n selector: 'bs-typeahead',\n templateUrl: './typeahead.component.html',\n styleUrls: ['./typeahead.component.scss'],\n imports: [\n FormsModule,\n BsFormComponent, BsFormControlDirective,\n BsDropdownDirective, BsDropdownMenuDirective, BsDropdownMenuComponent, BsDropdownItemComponent,\n BsComboboxDirective,\n BsRovingFocusDirective, BsRovingFocusItemDirective,\n BsProgressComponent, BsHasOverlayComponent,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class BsTypeaheadComponent {\n private announcer = inject(BsLiveAnnouncerService);\n\n isOpen = model(false);\n\n suggestions = input<any[]>([]);\n isLoading = signal<boolean>(false);\n showNoSuggestions = computed(() => this.suggestions().length === 0);\n\n readonly textbox = viewChild.required<ElementRef<HTMLInputElement>>('textbox');\n readonly rovingFocus = viewChild(BsRovingFocusDirective);\n searchterm = model('');\n isLoadingText = input('Loading...');\n noSuggestionsText = input('No suggestions found');\n resultsAnnouncementSingular = input<string>('1 result found');\n resultsAnnouncementPlural = input<(count: number) => string>((count) => `${count} results found`);\n provideSuggestions = output<string>();\n suggestionSelected = output<any>();\n submitted = output<string>();\n\n private requestInFlight = false;\n\n constructor() {\n effect(() => {\n const suggestions = this.suggestions();\n if (suggestions) {\n this.isLoading.set(false);\n if (this.requestInFlight) {\n this.requestInFlight = false;\n this.announceResults(suggestions.length);\n }\n }\n });\n }\n\n private announceResults(count: number) {\n if (count === 0) {\n this.announcer.announce(this.noSuggestionsText());\n } else if (count === 1) {\n this.announcer.announce(this.resultsAnnouncementSingular());\n } else {\n this.announcer.announce(this.resultsAnnouncementPlural()(count));\n }\n }\n\n onProvideSuggestions(value: string) {\n this.searchterm.set(value);\n if (value === '') {\n this.isOpen.set(false);\n this.requestInFlight = false;\n } else {\n this.requestInFlight = true;\n this.isLoading.set(true);\n this.isOpen.set(true);\n this.provideSuggestions.emit(value);\n }\n }\n\n suggestionClicked(suggestion: any) {\n this.searchterm.set(suggestion.text);\n this.isOpen.set(false);\n this.suggestionSelected.emit(suggestion);\n }\n\n onActivate() {\n const rf = this.rovingFocus();\n if (!rf) return;\n const suggestion = this.suggestions()[rf.activeIndex()];\n if (suggestion) {\n this.suggestionClicked(suggestion);\n }\n }\n\n onCancel() {\n // dropdown was already closed by bsCombobox; no extra work needed\n }\n\n onSubmit(event?: Event) {\n // Suppress browser form-submit; we own the Enter semantics here.\n event?.preventDefault();\n this.isOpen.set(false);\n this.submitted.emit(this.searchterm());\n }\n\n public focus() {\n this.textbox().nativeElement.focus();\n }\n}\n","<bs-has-overlay></bs-has-overlay>\n<bs-form>\n <div bsDropdown popupRole=\"listbox\" [(isOpen)]=\"isOpen\" [hasBackdrop]=\"false\" [sameDropdownWidth]=\"true\">\n <input type=\"text\"\n #textbox\n [ngModel]=\"searchterm()\"\n (ngModelChange)=\"onProvideSuggestions($event)\"\n bsCombobox\n (activate)=\"onActivate()\"\n (cancel)=\"onCancel()\"\n (keydown.enter)=\"onSubmit($event)\"\n autocomplete=\"off\" />\n <bs-dropdown-menu *bsDropdownMenu bsRovingFocus mode=\"activedescendant\">\n @if (isLoading()) {\n <bs-progress [height]=\"2\" [isIndeterminate]=\"true\"></bs-progress>\n <bs-dropdown-item [disabled]=\"true\">\n {{ isLoadingText() }}\n </bs-dropdown-item>\n }\n @if (!isLoading()) {\n @if (showNoSuggestions()) {\n <bs-dropdown-item [disabled]=\"true\">\n {{ noSuggestionsText() }}\n </bs-dropdown-item>\n }\n @for (suggestion of suggestions(); track suggestion) {\n <bs-dropdown-item bsRovingFocusItem (click)=\"suggestionClicked(suggestion)\">\n {{ suggestion.text }}\n </bs-dropdown-item>\n }\n }\n </bs-dropdown-menu>\n </div>\n</bs-form>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, signal, ChangeDetectionStrategy, Component, TemplateRef, Directive } from '@angular/core';
2
+ import { inject, ElementRef, input, signal, effect, ChangeDetectionStrategy, Component, TemplateRef, Directive } from '@angular/core';
3
3
  import { NgTemplateOutlet } from '@angular/common';
4
4
  import * as i1 from '@angular/cdk/scrolling';
5
5
  import { ScrollingModule } from '@angular/cdk/scrolling';
@@ -11,13 +11,28 @@ import { startWith, map, filter, distinctUntilChanged, switchMap, catchError } f
11
11
 
12
12
  class BsVirtualDatatableComponent extends DatatableSortBase {
13
13
  constructor() {
14
- super(...arguments);
14
+ super();
15
15
  this.elementRef = inject(ElementRef);
16
16
  this.cleanup = [];
17
17
  this.dataSource = input.required(...(ngDevMode ? [{ debugName: "dataSource" }] : /* istanbul ignore next */ []));
18
18
  this.isResponsive = input(false, ...(ngDevMode ? [{ debugName: "isResponsive" }] : /* istanbul ignore next */ []));
19
19
  this.itemSize = input(48, ...(ngDevMode ? [{ debugName: "itemSize" }] : /* istanbul ignore next */ []));
20
20
  this.rowTemplate = signal(undefined, ...(ngDevMode ? [{ debugName: "rowTemplate" }] : /* istanbul ignore next */ []));
21
+ /**
22
+ * Total logical row count for ARIA = data rows + 1 header row.
23
+ * Stays in sync with `dataSource.length$` so SR users hear "row 47 of
24
+ * 10000" even though the DOM only renders the visible viewport.
25
+ */
26
+ this.totalRowCount = signal(1, ...(ngDevMode ? [{ debugName: "totalRowCount" }] : /* istanbul ignore next */ []));
27
+ effect((onCleanup) => {
28
+ const ds = this.dataSource();
29
+ if (!ds) {
30
+ this.totalRowCount.set(1);
31
+ return;
32
+ }
33
+ const sub = ds.length$.subscribe((n) => this.totalRowCount.set(n + 1));
34
+ onCleanup(() => sub.unsubscribe());
35
+ });
21
36
  }
22
37
  ngAfterViewInit() {
23
38
  this.setupScrollSync();
@@ -146,22 +161,28 @@ class BsVirtualDatatableComponent extends DatatableSortBase {
146
161
  observer.observe(bodyTableBody, { childList: true, subtree: true });
147
162
  this.cleanup.push(() => observer.disconnect());
148
163
  }
149
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsVirtualDatatableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
150
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BsVirtualDatatableComponent, isStandalone: true, selector: "bs-virtual-datatable", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, isResponsive: { classPropertyName: "isResponsive", publicName: "isResponsive", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable()\"\n [class.sort-asc]=\"column.sortable() && getSortDirection(column.name()) === 'ascending'\"\n [class.sort-desc]=\"column.sortable() && getSortDirection(column.name()) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name()) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name()) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate()) {\n <ng-container *ngTemplateOutlet=\"rowTemplate()!; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto;width:max-content}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border"] }, { kind: "component", type: BsTableStylesComponent, selector: "bs-table-styles" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
164
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsVirtualDatatableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
165
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: BsVirtualDatatableComponent, isStandalone: true, selector: "bs-virtual-datatable", inputs: { dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: true, transformFunction: null }, isResponsive: { classPropertyName: "isResponsive", publicName: "isResponsive", isSignal: true, isRequired: false, transformFunction: null }, itemSize: { classPropertyName: "itemSize", publicName: "itemSize", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\" [ariaRowCount]=\"totalRowCount()\">\n <thead>\n <tr [attr.aria-rowindex]=\"1\">\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable()\"\n [class.sort-asc]=\"column.sortable() && getSortDirection(column.name()) === 'ascending'\"\n [class.sort-desc]=\"column.sortable() && getSortDirection(column.name()) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name()) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name()) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\" [attr.aria-rowcount]=\"totalRowCount()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource(); let i = index\" class=\"virtual-row\" [attr.aria-rowindex]=\"i + 2\">\n @if (item && rowTemplate()) {\n <ng-container *ngTemplateOutlet=\"rowTemplate()!; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}.virtual-datatable-container bs-table ::ng-deep table,.virtual-datatable-container .virtual-scroll-viewport table{table-layout:auto;width:max-content}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border", "ariaRowCount"] }, { kind: "component", type: BsTableStylesComponent, selector: "bs-table-styles" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
151
166
  }
152
167
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: BsVirtualDatatableComponent, decorators: [{
153
168
  type: Component,
154
- args: [{ selector: 'bs-virtual-datatable', imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\">\n <thead>\n <tr>\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable()\"\n [class.sort-asc]=\"column.sortable() && getSortDirection(column.name()) === 'ascending'\"\n [class.sort-desc]=\"column.sortable() && getSortDirection(column.name()) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name()) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name()) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource()\" class=\"virtual-row\">\n @if (item && rowTemplate()) {\n <ng-container *ngTemplateOutlet=\"rowTemplate()!; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}bs-table ::ng-deep table,.virtual-scroll-viewport table{table-layout:auto;width:max-content}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"] }]
155
- }], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], isResponsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isResponsive", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }] } });
169
+ args: [{ selector: 'bs-virtual-datatable', imports: [NgTemplateOutlet, ScrollingModule, BsTableComponent, BsTableStylesComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"virtual-datatable-container\">\n <bs-table [isResponsive]=\"isResponsive()\" [striped]=\"true\" [hover]=\"true\" [ariaRowCount]=\"totalRowCount()\">\n <thead>\n <tr [attr.aria-rowindex]=\"1\">\n @for (column of columnsArray; track column) {\n <th class=\"text-nowrap\"\n [class.sort]=\"column.sortable()\"\n [class.sort-asc]=\"column.sortable() && getSortDirection(column.name()) === 'ascending'\"\n [class.sort-desc]=\"column.sortable() && getSortDirection(column.name()) === 'descending'\"\n (mousedown)=\"onHeaderMouseDown($event)\"\n (click)=\"columnHeaderClicked(column, $event)\">\n <ng-container *ngTemplateOutlet=\"column.templateRef\"></ng-container>\n @if (settings().sortColumns.length > 1 && getSortIndex(column.name()) >= 0) {\n <span class=\"sort-priority\">{{ getSortIndex(column.name()) + 1 }}</span>\n }\n </th>\n }\n </tr>\n </thead>\n </bs-table>\n\n <bs-table-styles>\n <cdk-virtual-scroll-viewport [itemSize]=\"itemSize()\" class=\"virtual-scroll-viewport\">\n <table class=\"table table-striped table-hover\" [class.nowrap]=\"isResponsive()\" [attr.aria-rowcount]=\"totalRowCount()\">\n <tbody>\n <tr *cdkVirtualFor=\"let item of dataSource(); let i = index\" class=\"virtual-row\" [attr.aria-rowindex]=\"i + 2\">\n @if (item && rowTemplate()) {\n <ng-container *ngTemplateOutlet=\"rowTemplate()!; context: { $implicit: item }\"></ng-container>\n } @else {\n @for (column of columnsArray; track column) {\n <td>&nbsp;</td>\n }\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n </bs-table-styles>\n</div>\n", styles: ["@charset \"UTF-8\";bs-table thead th.sort{position:relative;cursor:pointer;padding-right:2rem}bs-table thead th.sort:before,bs-table thead th.sort:after{position:absolute;display:block;opacity:.3;bottom:.5em}bs-table thead th.sort:before{content:\"\\2191\";right:1em}bs-table thead th.sort:after{content:\"\\2193\";right:.5em}bs-table thead th.sort.sort-asc:after{opacity:1}bs-table thead th.sort.sort-desc:before{opacity:1}bs-table thead th.sort .sort-priority{position:absolute;right:.1em;bottom:.3em;font-size:.65em;font-weight:700;opacity:.7}:host{display:block;height:100%}.virtual-datatable-container{display:flex;flex-direction:column;height:100%}.virtual-datatable-container bs-table{flex-shrink:0}.virtual-datatable-container bs-table ::ng-deep table,.virtual-datatable-container .virtual-scroll-viewport table{table-layout:auto;width:max-content}.virtual-scroll-viewport .nowrap td{white-space:nowrap}bs-table ::ng-deep .table-responsive{overflow-x:hidden;scrollbar-gutter:stable}.virtual-scroll-viewport{flex:1 1 auto;min-height:0;scrollbar-gutter:stable}.virtual-scroll-viewport table{margin-bottom:0}\n"] }]
170
+ }], ctorParameters: () => [], propDecorators: { dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: true }] }], isResponsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isResponsive", required: false }] }], itemSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemSize", required: false }] }] } });
156
171
 
157
172
  class VirtualDatatableDataSource extends DataSource {
158
173
  constructor(fetchFn, pageSize = 50) {
159
174
  super();
160
175
  this.cachedPages = new Map();
161
- this.totalRecords = 0;
176
+ this.totalRecords$ = new BehaviorSubject(0);
162
177
  this.dataStream = new BehaviorSubject([]);
163
178
  this.resetSubject = new Subject();
164
179
  this.resetVersion = 0;
180
+ /**
181
+ * Emits the current total record count. Backed by the same value as
182
+ * `length`, but observable so consumers (e.g. virtual-datatable's ARIA
183
+ * row-count binding) can react to it without polling.
184
+ */
185
+ this.length$ = this.totalRecords$.asObservable();
165
186
  this.fetchFn = fetchFn;
166
187
  this.pageSize = pageSize;
167
188
  }
@@ -169,7 +190,7 @@ class VirtualDatatableDataSource extends DataSource {
169
190
  // Support reconnection after disconnect (which completes the previous dataStream)
170
191
  this.dataStream = new BehaviorSubject([]);
171
192
  this.cachedPages.clear();
172
- this.totalRecords = 0;
193
+ this.totalRecords$.next(0);
173
194
  // Track the last viewport range so reset() can re-trigger a fetch.
174
195
  // resetVersion is incremented on reset() to bypass distinctUntilChanged.
175
196
  let lastRange = { start: 0, end: this.pageSize };
@@ -181,7 +202,7 @@ class VirtualDatatableDataSource extends DataSource {
181
202
  this.dataStream.complete();
182
203
  }
183
204
  get length() {
184
- return this.totalRecords;
205
+ return this.totalRecords$.value;
185
206
  }
186
207
  reset() {
187
208
  this.cachedPages.clear();
@@ -208,10 +229,11 @@ class VirtualDatatableDataSource extends DataSource {
208
229
  this.cachedPages.set(pageIndex, result.data);
209
230
  }
210
231
  if (results.length > 0) {
211
- this.totalRecords = results[0].result.totalRecords;
232
+ this.totalRecords$.next(results[0].result.totalRecords);
212
233
  }
213
234
  // Build the full data array with placeholders for unloaded pages
214
- const totalPages = Math.ceil(this.totalRecords / this.pageSize);
235
+ const totalRecords = this.totalRecords$.value;
236
+ const totalPages = Math.ceil(totalRecords / this.pageSize);
215
237
  const data = [];
216
238
  for (let i = 0; i < totalPages; i++) {
217
239
  const page = this.cachedPages.get(i);
@@ -220,7 +242,7 @@ class VirtualDatatableDataSource extends DataSource {
220
242
  }
221
243
  else {
222
244
  // Fill with empty slots to maintain correct virtual scroll positioning
223
- const remaining = Math.min(this.pageSize, this.totalRecords - i * this.pageSize);
245
+ const remaining = Math.min(this.pageSize, totalRecords - i * this.pageSize);
224
246
  data.push(...new Array(remaining));
225
247
  }
226
248
  }