@siemens/element-ng 49.10.0 → 49.12.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 (108) hide show
  1. package/carousel/package.json +4 -0
  2. package/fesm2022/siemens-element-ng-about.mjs +13 -4
  3. package/fesm2022/siemens-element-ng-about.mjs.map +1 -1
  4. package/fesm2022/siemens-element-ng-ag-grid.mjs +6 -5
  5. package/fesm2022/siemens-element-ng-ag-grid.mjs.map +1 -1
  6. package/fesm2022/siemens-element-ng-application-header.mjs +21 -24
  7. package/fesm2022/siemens-element-ng-application-header.mjs.map +1 -1
  8. package/fesm2022/siemens-element-ng-breadcrumb-router.mjs +3 -3
  9. package/fesm2022/siemens-element-ng-breadcrumb-router.mjs.map +1 -1
  10. package/fesm2022/siemens-element-ng-breadcrumb.mjs +3 -3
  11. package/fesm2022/siemens-element-ng-breadcrumb.mjs.map +1 -1
  12. package/fesm2022/siemens-element-ng-card.mjs +2 -2
  13. package/fesm2022/siemens-element-ng-card.mjs.map +1 -1
  14. package/fesm2022/siemens-element-ng-carousel.mjs +541 -0
  15. package/fesm2022/siemens-element-ng-carousel.mjs.map +1 -0
  16. package/fesm2022/siemens-element-ng-chat-messages.mjs +18 -21
  17. package/fesm2022/siemens-element-ng-chat-messages.mjs.map +1 -1
  18. package/fesm2022/siemens-element-ng-content-action-bar.mjs +2 -2
  19. package/fesm2022/siemens-element-ng-content-action-bar.mjs.map +1 -1
  20. package/fesm2022/siemens-element-ng-dashboard.mjs +34 -35
  21. package/fesm2022/siemens-element-ng-dashboard.mjs.map +1 -1
  22. package/fesm2022/siemens-element-ng-date-range-filter.mjs +20 -9
  23. package/fesm2022/siemens-element-ng-date-range-filter.mjs.map +1 -1
  24. package/fesm2022/siemens-element-ng-datepicker.mjs +11 -10
  25. package/fesm2022/siemens-element-ng-datepicker.mjs.map +1 -1
  26. package/fesm2022/siemens-element-ng-electron-titlebar.mjs +3 -3
  27. package/fesm2022/siemens-element-ng-electron-titlebar.mjs.map +1 -1
  28. package/fesm2022/siemens-element-ng-empty-state.mjs +2 -2
  29. package/fesm2022/siemens-element-ng-empty-state.mjs.map +1 -1
  30. package/fesm2022/siemens-element-ng-file-uploader.mjs +49 -47
  31. package/fesm2022/siemens-element-ng-file-uploader.mjs.map +1 -1
  32. package/fesm2022/siemens-element-ng-filter-bar.mjs +5 -5
  33. package/fesm2022/siemens-element-ng-filter-bar.mjs.map +1 -1
  34. package/fesm2022/siemens-element-ng-filtered-search.mjs +8 -7
  35. package/fesm2022/siemens-element-ng-filtered-search.mjs.map +1 -1
  36. package/fesm2022/siemens-element-ng-footer.mjs +3 -3
  37. package/fesm2022/siemens-element-ng-footer.mjs.map +1 -1
  38. package/fesm2022/siemens-element-ng-form.mjs +11 -10
  39. package/fesm2022/siemens-element-ng-form.mjs.map +1 -1
  40. package/fesm2022/siemens-element-ng-formly.mjs +24 -23
  41. package/fesm2022/siemens-element-ng-formly.mjs.map +1 -1
  42. package/fesm2022/siemens-element-ng-header-dropdown.mjs +26 -17
  43. package/fesm2022/siemens-element-ng-header-dropdown.mjs.map +1 -1
  44. package/fesm2022/siemens-element-ng-help-button.mjs +3 -3
  45. package/fesm2022/siemens-element-ng-help-button.mjs.map +1 -1
  46. package/fesm2022/siemens-element-ng-inline-notification.mjs +3 -3
  47. package/fesm2022/siemens-element-ng-inline-notification.mjs.map +1 -1
  48. package/fesm2022/siemens-element-ng-landing-page.mjs +2 -2
  49. package/fesm2022/siemens-element-ng-landing-page.mjs.map +1 -1
  50. package/fesm2022/siemens-element-ng-language-switcher.mjs +3 -3
  51. package/fesm2022/siemens-element-ng-language-switcher.mjs.map +1 -1
  52. package/fesm2022/siemens-element-ng-markdown-renderer.mjs +4 -3
  53. package/fesm2022/siemens-element-ng-markdown-renderer.mjs.map +1 -1
  54. package/fesm2022/siemens-element-ng-menu.mjs +2 -2
  55. package/fesm2022/siemens-element-ng-menu.mjs.map +1 -1
  56. package/fesm2022/siemens-element-ng-navbar-vertical-next.mjs +362 -264
  57. package/fesm2022/siemens-element-ng-navbar-vertical-next.mjs.map +1 -1
  58. package/fesm2022/siemens-element-ng-navbar-vertical.mjs +30 -13
  59. package/fesm2022/siemens-element-ng-navbar-vertical.mjs.map +1 -1
  60. package/fesm2022/siemens-element-ng-navbar.mjs +6 -8
  61. package/fesm2022/siemens-element-ng-navbar.mjs.map +1 -1
  62. package/fesm2022/siemens-element-ng-notification-item.mjs +3 -3
  63. package/fesm2022/siemens-element-ng-notification-item.mjs.map +1 -1
  64. package/fesm2022/siemens-element-ng-pagination.mjs +4 -1
  65. package/fesm2022/siemens-element-ng-pagination.mjs.map +1 -1
  66. package/fesm2022/siemens-element-ng-password-toggle.mjs +3 -3
  67. package/fesm2022/siemens-element-ng-password-toggle.mjs.map +1 -1
  68. package/fesm2022/siemens-element-ng-photo-upload.mjs +2 -2
  69. package/fesm2022/siemens-element-ng-pills-input.mjs +4 -4
  70. package/fesm2022/siemens-element-ng-pills-input.mjs.map +1 -1
  71. package/fesm2022/siemens-element-ng-popover-legacy.mjs +3 -3
  72. package/fesm2022/siemens-element-ng-popover-legacy.mjs.map +1 -1
  73. package/fesm2022/siemens-element-ng-popover.mjs +3 -3
  74. package/fesm2022/siemens-element-ng-popover.mjs.map +1 -1
  75. package/fesm2022/siemens-element-ng-result-details-list.mjs +3 -3
  76. package/fesm2022/siemens-element-ng-result-details-list.mjs.map +1 -1
  77. package/fesm2022/siemens-element-ng-select.mjs +2 -2
  78. package/fesm2022/siemens-element-ng-side-panel.mjs +6 -6
  79. package/fesm2022/siemens-element-ng-side-panel.mjs.map +1 -1
  80. package/fesm2022/siemens-element-ng-sort-bar.mjs +3 -3
  81. package/fesm2022/siemens-element-ng-sort-bar.mjs.map +1 -1
  82. package/fesm2022/siemens-element-ng-split.mjs +3 -3
  83. package/fesm2022/siemens-element-ng-split.mjs.map +1 -1
  84. package/fesm2022/siemens-element-ng-status-bar.mjs +3 -3
  85. package/fesm2022/siemens-element-ng-status-bar.mjs.map +1 -1
  86. package/fesm2022/siemens-element-ng-threshold.mjs +5 -5
  87. package/fesm2022/siemens-element-ng-threshold.mjs.map +1 -1
  88. package/fesm2022/siemens-element-ng-toast-notification.mjs +3 -3
  89. package/fesm2022/siemens-element-ng-toast-notification.mjs.map +1 -1
  90. package/fesm2022/siemens-element-ng-tooltip.mjs +3 -3
  91. package/fesm2022/siemens-element-ng-tooltip.mjs.map +1 -1
  92. package/fesm2022/siemens-element-ng-tour.mjs +2 -2
  93. package/fesm2022/siemens-element-ng-translate.mjs.map +1 -1
  94. package/fesm2022/siemens-element-ng-tree-view.mjs +6 -6
  95. package/fesm2022/siemens-element-ng-tree-view.mjs.map +1 -1
  96. package/package.json +12 -8
  97. package/template-i18n.json +15 -6
  98. package/types/siemens-element-ng-about.d.ts +11 -1
  99. package/types/siemens-element-ng-application-header.d.ts +3 -4
  100. package/types/siemens-element-ng-carousel.d.ts +209 -0
  101. package/types/siemens-element-ng-chat-messages.d.ts +1 -2
  102. package/types/siemens-element-ng-dashboard.d.ts +4 -4
  103. package/types/siemens-element-ng-date-range-filter.d.ts +11 -2
  104. package/types/siemens-element-ng-file-uploader.d.ts +6 -8
  105. package/types/siemens-element-ng-header-dropdown.d.ts +3 -3
  106. package/types/siemens-element-ng-navbar-vertical-next.d.ts +161 -85
  107. package/types/siemens-element-ng-navbar.d.ts +1 -2
  108. package/types/siemens-element-ng-translate.d.ts +9 -0
@@ -0,0 +1,541 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, computed, ElementRef, signal, Directive, input, booleanAttribute, contentChildren, linkedSignal, DestroyRef, viewChild, ChangeDetectorRef, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { toSignal, toObservable } from '@angular/core/rxjs-interop';
4
+ import { elementPause, elementPlay, elementRight2, elementLeft2 } from '@siemens/element-icons';
5
+ import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
6
+ import { SiResizeObserverDirective } from '@siemens/element-ng/resize-observer';
7
+ import { t, injectSiTranslateService, SiTranslatePipe } from '@siemens/element-translate-ng/translate';
8
+ import { switchMap } from 'rxjs';
9
+
10
+ /**
11
+ * Copyright (c) Siemens 2016 - 2026
12
+ * SPDX-License-Identifier: MIT
13
+ */
14
+ class SiCarouselItemDirective {
15
+ carousel = inject(SiCarouselComponent);
16
+ isVisible = computed(() => {
17
+ if (this.carousel.currentActiveSlide() === this.elementRef) {
18
+ return true;
19
+ }
20
+ return false;
21
+ }, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
22
+ /** @internal */
23
+ elementRef = inject(ElementRef);
24
+ /** @internal */
25
+ order = signal(0, ...(ngDevMode ? [{ debugName: "order" }] : []));
26
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiCarouselItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
27
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.8", type: SiCarouselItemDirective, isStandalone: true, selector: "[siCarouselItem]", host: { attributes: { "role": "group" }, properties: { "style.order": "order()", "attr.aria-roledescription": "carousel.translatedSlideRoleDescription()", "attr.inert": "isVisible() ? null : \"\"", "attr.aria-hidden": "isVisible() ? null : \"true\"" }, styleAttribute: "flex-shrink: 0; flex-basis: 100%; scroll-snap-align: center;" }, ngImport: i0 });
28
+ }
29
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiCarouselItemDirective, decorators: [{
30
+ type: Directive,
31
+ args: [{
32
+ selector: '[siCarouselItem]',
33
+ host: {
34
+ style: 'flex-shrink: 0; flex-basis: 100%; scroll-snap-align: center;',
35
+ '[style.order]': 'order()',
36
+ 'role': 'group',
37
+ '[attr.aria-roledescription]': 'carousel.translatedSlideRoleDescription()',
38
+ '[attr.inert]': 'isVisible() ? null : ""',
39
+ '[attr.aria-hidden]': 'isVisible() ? null : "true"'
40
+ }
41
+ }]
42
+ }] });
43
+
44
+ /**
45
+ * Copyright (c) Siemens 2016 - 2026
46
+ * SPDX-License-Identifier: MIT
47
+ */
48
+ /**
49
+ * Maximum number of pagination dots shown in the pager.
50
+ */
51
+ const MAX_PAGES = 5;
52
+ /**
53
+ * Time constant (in milliseconds) for the exponential-smoothing scroll animation. Smaller values
54
+ * settle faster. The animation is retargetable, so rapid clicks keep adjusting the same animation
55
+ * towards the latest slide instead of starting separate, queued scrolls.
56
+ */
57
+ const SCROLL_SMOOTHING_TAU = 100;
58
+ /**
59
+ * Assumed duration (in milliseconds) of the first animation frame, used before two timestamps are
60
+ * available to measure a real delta. 16ms corresponds to one frame at ~60Hz, a safe default that
61
+ * keeps the first easing step the same size as a normal frame.
62
+ */
63
+ const FIRST_FRAME_DELTA = 16;
64
+ /**
65
+ * Distance (in CSS pixels) below which the viewport is considered to have reached its target. Less
66
+ * than a pixel is imperceptible, so the animation snaps to the target and stops instead of easing
67
+ * across ever-smaller, invisible fractions of a pixel forever.
68
+ */
69
+ const SCROLL_SETTLE_THRESHOLD = 0.5;
70
+ /**
71
+ * Per-frame progress (in CSS pixels) below which the animation is treated as stalled. The browser
72
+ * can cap `scrollLeft` a sub-pixel short of the computed target at the scroll boundary; without
73
+ * this guard the loop would never reach the target and would spin forever. Kept below
74
+ * {@link SCROLL_SETTLE_THRESHOLD} so it only triggers when real movement has effectively stopped.
75
+ */
76
+ const SCROLL_STALL_THRESHOLD = 0.25;
77
+ /**
78
+ * A carousel component for displaying slides with navigation controls and auto-play.
79
+ *
80
+ * Features horizontal scrolling with snap behavior, pagination dots, and ARIA accessibility.
81
+ * Suitable for dashboards, image galleries, and content showcases.
82
+ *
83
+ * @example
84
+ *
85
+ * ```typescript
86
+ * import { SiCarouselComponent, SiCarouselItemDirective } from '@siemens/element-ng/carousel';
87
+ *
88
+ * @Component({
89
+ * imports: [SiCarouselComponent, SiCarouselItemDirective],
90
+ * template: `
91
+ * <si-carousel>
92
+ * <div siCarouselItem><h2>Slide 1</h2></div>
93
+ * <div siCarouselItem><h2>Slide 2</h2></div>
94
+ * <div siCarouselItem><h2>Slide 3</h2></div>
95
+ * </si-carousel>
96
+ * `
97
+ * })
98
+ * export class MyComponent {}
99
+ * ```
100
+ */
101
+ class SiCarouselComponent {
102
+ /**
103
+ * Controls whether pagination controls are shown.
104
+ * When `true`, the carousel shows one slide per page and hides pagination controls.
105
+ * @defaultValue false
106
+ * */
107
+ hidePageControls = input(false, { ...(ngDevMode ? { debugName: "hidePageControls" } : {}), transform: booleanAttribute });
108
+ /**
109
+ * Enables or configures auto-play for the carousel. When set to `true`, the carousel automatically
110
+ * navigates to the next slide every 5000 milliseconds (5 seconds). Pass a positive number to set a
111
+ * custom interval in milliseconds. Pass `false` to disable auto-play.
112
+ * @defaultValue false
113
+ * */
114
+ autoPlay = input(false, ...(ngDevMode ? [{ debugName: "autoPlay" }] : []));
115
+ /**
116
+ * Aria role of the carousel element. Can be set to 'region' or 'group' depending on the desired accessibility semantics.
117
+ * @defaultValue 'region'
118
+ * */
119
+ ariaRole = input('region', ...(ngDevMode ? [{ debugName: "ariaRole" }] : []));
120
+ /**
121
+ * Aria label for the previous button, used for accessibility purposes.
122
+ * @defaultValue
123
+ * ```
124
+ * t(() => $localize`:@@SI_CAROUSEL.PREVIOUS:Previous slide`)
125
+ * ```
126
+ */
127
+ previousButtonAriaLabel = input(t(() => $localize `:@@SI_CAROUSEL.PREVIOUS:Previous slide`), ...(ngDevMode ? [{ debugName: "previousButtonAriaLabel" }] : []));
128
+ /**
129
+ * Aria label for the next button, used for accessibility purposes.
130
+ * @defaultValue
131
+ * ```
132
+ * t(() => $localize`:@@SI_CAROUSEL.NEXT:Next slide`)
133
+ * ```
134
+ */
135
+ nextButtonAriaLabel = input(t(() => $localize `:@@SI_CAROUSEL.NEXT:Next slide`), ...(ngDevMode ? [{ debugName: "nextButtonAriaLabel" }] : []));
136
+ /**
137
+ * @defaultValue
138
+ * ```
139
+ * t(() => $localize`:@@SI_CAROUSEL.SLIDE_PAGE:Slide {{page}} of {{total}}`)
140
+ * ```
141
+ */
142
+ slidePageAriaLabel = input(t(() => $localize `:@@SI_CAROUSEL.SLIDE_PAGE:Slide {{page}} of {{total}}`), ...(ngDevMode ? [{ debugName: "slidePageAriaLabel" }] : []));
143
+ /**
144
+ * Label for the play button when autoplay is paused.
145
+ * @defaultValue
146
+ * ```
147
+ * t(() => $localize`:@@SI_CAROUSEL.PLAY:Play`)
148
+ * ```
149
+ */
150
+ playButtonLabel = input(t(() => $localize `:@@SI_CAROUSEL.PLAY:Play`), ...(ngDevMode ? [{ debugName: "playButtonLabel" }] : []));
151
+ /**
152
+ * Label for the pause button when autoplay is active.
153
+ * @defaultValue
154
+ * ```
155
+ * t(() => $localize`:@@SI_CAROUSEL.PAUSE:Pause`)
156
+ * ```
157
+ */
158
+ pauseButtonLabel = input(t(() => $localize `:@@SI_CAROUSEL.PAUSE:Pause`), ...(ngDevMode ? [{ debugName: "pauseButtonLabel" }] : []));
159
+ /**
160
+ * Role description for the carousel container, used for accessibility purposes.
161
+ * @defaultValue
162
+ * ```
163
+ * t(() => $localize`:@@SI_CAROUSEL.ROLE_DESCRIPTION:carousel`)
164
+ * ```
165
+ */
166
+ carouselRoleDescription = input(t(() => $localize `:@@SI_CAROUSEL.ROLE_DESCRIPTION:carousel`), ...(ngDevMode ? [{ debugName: "carouselRoleDescription" }] : []));
167
+ /**
168
+ * Role description for each slide, used for accessibility purposes.
169
+ * @defaultValue
170
+ * ```
171
+ * t(() => $localize`:@@SI_CAROUSEL.SLIDE_ROLE_DESCRIPTION:Slide`)
172
+ * ```
173
+ */
174
+ slideRoleDescription = input(t(() => $localize `:@@SI_CAROUSEL.SLIDE_ROLE_DESCRIPTION:Slide`), ...(ngDevMode ? [{ debugName: "slideRoleDescription" }] : []));
175
+ /** @internal */
176
+ translatedSlideRoleDescription = toSignal(toObservable(this.slideRoleDescription).pipe(switchMap(key => this.translateService.translateAsync(key))), { initialValue: '' });
177
+ /** @internal */
178
+ currentActiveSlide = computed(() => {
179
+ const currentPage = this.currentPage();
180
+ if (currentPage !== null && this.items().length) {
181
+ return this.items()[currentPage].elementRef;
182
+ }
183
+ return null;
184
+ }, ...(ngDevMode ? [{ debugName: "currentActiveSlide" }] : []));
185
+ translatedCarouselRoleDescription = toSignal(toObservable(this.carouselRoleDescription).pipe(switchMap(key => this.translateService.translateAsync(key))), { initialValue: '' });
186
+ items = contentChildren(SiCarouselItemDirective, ...(ngDevMode ? [{ debugName: "items" }] : []));
187
+ currentPage = linkedSignal(() => this.items().length ? 0 : null, ...(ngDevMode ? [{ debugName: "currentPage" }] : []));
188
+ isPaused = signal(false, ...(ngDevMode ? [{ debugName: "isPaused" }] : []));
189
+ totalPages = computed(() => this.items().length, ...(ngDevMode ? [{ debugName: "totalPages" }] : []));
190
+ edgeLeftIndex = signal(0, ...(ngDevMode ? [{ debugName: "edgeLeftIndex" }] : []));
191
+ edgeRightIndex = signal(MAX_PAGES - 1, ...(ngDevMode ? [{ debugName: "edgeRightIndex" }] : []));
192
+ insufficientSpace = signal(false, ...(ngDevMode ? [{ debugName: "insufficientSpace" }] : []));
193
+ pageControlContainerMinWidth = signal(0, ...(ngDevMode ? [{ debugName: "pageControlContainerMinWidth" }] : []));
194
+ icons = addIcons({ elementLeft2, elementRight2, elementPlay, elementPause });
195
+ autoPlayDuration = computed(() => {
196
+ const autoPlayValue = this.autoPlay();
197
+ if (typeof autoPlayValue === 'boolean') {
198
+ return autoPlayValue ? 5000 : 0;
199
+ }
200
+ return autoPlayValue > 0 ? autoPlayValue : 0;
201
+ }, ...(ngDevMode ? [{ debugName: "autoPlayDuration" }] : []));
202
+ intervalId = null;
203
+ scrollObserver = null;
204
+ /** requestAnimationFrame id of the running scroll animation, or null when idle. */
205
+ animationFrameId = null;
206
+ /** Scroll position (`scrollLeft`) the running animation is easing towards. */
207
+ animationTargetLeft = 0;
208
+ /** Timestamp of the previous animation frame, used to make the easing frame-rate independent. */
209
+ lastFrameTime = 0;
210
+ /** Whether any slide's CSS order has been changed from its natural (source-index) position. */
211
+ ordersModified = false;
212
+ destroyRef = inject(DestroyRef);
213
+ viewport = viewChild.required('viewport');
214
+ pageControl = viewChild('pageControl', ...(ngDevMode ? [{ debugName: "pageControl" }] : []));
215
+ playPauseBtn = viewChild('playPauseBtn', ...(ngDevMode ? [{ debugName: "playPauseBtn" }] : []));
216
+ translateService = injectSiTranslateService();
217
+ cdRef = inject(ChangeDetectorRef);
218
+ constructor() {
219
+ effect(onCleanup => {
220
+ this.scheduleAutoPlay();
221
+ onCleanup(() => clearInterval(this.intervalId));
222
+ });
223
+ effect(() => {
224
+ // Reset to the first page if the current page becomes out of range due to items being added/removed.
225
+ const currentPage = this.currentPage();
226
+ if (currentPage !== null && currentPage >= this.totalPages()) {
227
+ this.cancelAnimation();
228
+ this.items().forEach((_, i) => this.setSlideOrder(i, i));
229
+ this.ordersModified = false;
230
+ this.goToPage(0);
231
+ }
232
+ });
233
+ effect(() => {
234
+ this.setupScrollObserver();
235
+ });
236
+ effect(() => {
237
+ // Establish the canonical track order (each slide's CSS order equals its source index) so the
238
+ // navigation maths stay consistent. Skipped while an order change is mid-flight, where the
239
+ // orders are intentionally extended and normalized once the animation settles.
240
+ const items = this.items();
241
+ if (this.ordersModified) {
242
+ return;
243
+ }
244
+ items.forEach((_, i) => this.setSlideOrder(i, i));
245
+ });
246
+ effect(() => {
247
+ this.updateEdgeIndices();
248
+ });
249
+ this.destroyRef.onDestroy(() => {
250
+ if (this.animationFrameId !== null) {
251
+ cancelAnimationFrame(this.animationFrameId);
252
+ }
253
+ this.scrollObserver?.disconnect();
254
+ });
255
+ }
256
+ goToPage(page, forceScroll = true) {
257
+ this.currentPage.set(page);
258
+ this.scheduleAutoPlay();
259
+ if (forceScroll) {
260
+ this.animateToSlide(page);
261
+ }
262
+ }
263
+ next() {
264
+ this.step(1);
265
+ }
266
+ previous() {
267
+ this.step(-1);
268
+ }
269
+ /** Navigates directly to a specific slide, used by the pagination dots. */
270
+ goToSlide(index) {
271
+ this.cancelAnimation();
272
+ this.normalizeOrders();
273
+ this.goToPage(index, true);
274
+ }
275
+ toggleAutoPlay() {
276
+ this.isPaused.update(paused => !paused);
277
+ if (this.isPaused()) {
278
+ this.stopAutoPlay();
279
+ }
280
+ else {
281
+ this.scheduleAutoPlay();
282
+ }
283
+ }
284
+ onResize(size) {
285
+ const pageControl = this.pageControl();
286
+ if (!pageControl) {
287
+ return;
288
+ }
289
+ const pageControlWidth = pageControl.nativeElement.offsetWidth;
290
+ if (this.autoPlay()) {
291
+ const playPauseBtnWidth = this.playPauseBtn()?.nativeElement.offsetWidth ?? 0;
292
+ const minWidth = pageControlWidth + playPauseBtnWidth;
293
+ if (minWidth > size.width - playPauseBtnWidth) {
294
+ this.insufficientSpace.set(true);
295
+ }
296
+ else {
297
+ this.insufficientSpace.set(false);
298
+ }
299
+ this.pageControlContainerMinWidth.set(minWidth);
300
+ }
301
+ else {
302
+ this.insufficientSpace.set(false);
303
+ this.pageControlContainerMinWidth.set(pageControlWidth);
304
+ }
305
+ }
306
+ /**
307
+ * Navigates a single slide forward (`1`) or backward (`-1`). Rapid clicks are intentionally not
308
+ * queued or throttled: each click advances {@link currentPage} immediately and retargets the
309
+ * running scroll animation (see {@link animateTo}) towards the new slide, so the carousel keeps
310
+ * gliding in the click direction without waiting for the previous scroll to finish.
311
+ *
312
+ * To keep the first/last wrap a continuous one-slide glide instead of a jump across the whole
313
+ * track, the target slide's CSS order is placed exactly one slot away from the current slide in
314
+ * the click direction (so it sits adjacent to it). The viewport scroll is compensated so this
315
+ * reorder is invisible. Orders may extend while the user keeps clicking; they are silently
316
+ * normalized once the animation settles (see {@link normalizeOrders}).
317
+ */
318
+ step(direction) {
319
+ const total = this.totalPages();
320
+ if (total <= 1) {
321
+ return;
322
+ }
323
+ const from = this.currentPage() ?? 0;
324
+ const to = (from + direction + total) % total;
325
+ // Ensure the target slide sits one slot away from the current slide in the click direction.
326
+ // For a normal step it already does; for a first/last wrap it does not, so move it there.
327
+ const desiredOrder = this.items()[from].order() + direction;
328
+ if (this.items()[to].order() !== desiredOrder) {
329
+ this.reorderSlide(to, desiredOrder, from);
330
+ }
331
+ this.currentPage.set(to);
332
+ this.scheduleAutoPlay();
333
+ this.animateToSlide(to);
334
+ }
335
+ /**
336
+ * Changes a slide's CSS order while keeping the picture stable. Reordering shifts slides along
337
+ * the flex track, so the scroll position is adjusted by the exact amount the anchor slide moved,
338
+ * making the relocation invisible and letting any in-flight animation continue seamlessly.
339
+ */
340
+ reorderSlide(index, order, anchorIndex) {
341
+ const viewport = this.viewport().nativeElement;
342
+ const anchor = this.items()[anchorIndex].elementRef.nativeElement;
343
+ const before = anchor.getBoundingClientRect().left;
344
+ this.setSlideOrder(index, order);
345
+ // Reading layout after the order change forces a synchronous reflow with the new positions.
346
+ const after = anchor.getBoundingClientRect().left;
347
+ viewport.scrollLeft += after - before;
348
+ this.ordersModified = true;
349
+ }
350
+ /**
351
+ * Sets the CSS order of a slide. The value is written to the DOM synchronously in addition to
352
+ * the signal, so a subsequent reflow/scroll uses the new order immediately instead of waiting
353
+ * for the asynchronous, signal-driven change detection update.
354
+ */
355
+ setSlideOrder(index, order) {
356
+ const slide = this.items()[index];
357
+ slide.order.set(order);
358
+ slide.elementRef.nativeElement.style.order = `${order}`;
359
+ }
360
+ /**
361
+ * Silently restores the canonical slide order (each slide's CSS order equals its source index).
362
+ * Reordering shifts the track, so it anchors on the current slide and compensates the scroll
363
+ * position to avoid any visible jump. Called once the scroll animation settles.
364
+ */
365
+ normalizeOrders() {
366
+ if (!this.ordersModified) {
367
+ return;
368
+ }
369
+ const items = this.items();
370
+ const viewport = this.viewport().nativeElement;
371
+ const current = this.currentPage();
372
+ const anchor = current !== null ? items[current]?.elementRef.nativeElement : undefined;
373
+ const before = anchor?.getBoundingClientRect().left ?? 0;
374
+ for (let i = 0; i < items.length; i++) {
375
+ if (items[i].order() !== i) {
376
+ this.setSlideOrder(i, i);
377
+ }
378
+ }
379
+ if (anchor) {
380
+ const after = anchor.getBoundingClientRect().left;
381
+ viewport.scrollLeft += after - before;
382
+ }
383
+ this.ordersModified = false;
384
+ }
385
+ /** Animates the viewport so the given slide is horizontally centered. */
386
+ animateToSlide(index) {
387
+ const viewport = this.viewport().nativeElement;
388
+ const slide = this.items()[index].elementRef.nativeElement;
389
+ const viewportRect = viewport.getBoundingClientRect();
390
+ const slideRect = slide.getBoundingClientRect();
391
+ const delta = slideRect.left + slideRect.width / 2 - (viewportRect.left + viewportRect.width / 2);
392
+ this.animateTo(viewport.scrollLeft + delta);
393
+ }
394
+ /**
395
+ * Eases `scrollLeft` towards `targetLeft` using a frame-rate independent exponential smoothing
396
+ * loop. The target can be updated mid-flight (rapid clicks), so the same animation simply chases
397
+ * the latest slide. Native scroll-snap and smooth scroll-behavior are disabled while animating so
398
+ * they do not fight the manual scrolling, and the scroll observer is paused to avoid feedback.
399
+ */
400
+ animateTo(targetLeft) {
401
+ this.animationTargetLeft = targetLeft;
402
+ if (this.animationFrameId !== null) {
403
+ return;
404
+ }
405
+ const viewport = this.viewport().nativeElement;
406
+ this.scrollObserver?.disconnect();
407
+ viewport.style.scrollSnapType = 'none';
408
+ viewport.style.scrollBehavior = 'auto';
409
+ this.lastFrameTime = 0;
410
+ this.animationFrameId = requestAnimationFrame(time => this.animationFrame(time));
411
+ }
412
+ animationFrame(now) {
413
+ const viewport = this.viewport().nativeElement;
414
+ const dt = this.lastFrameTime ? now - this.lastFrameTime : FIRST_FRAME_DELTA;
415
+ this.lastFrameTime = now;
416
+ const current = viewport.scrollLeft;
417
+ // Clamp the target to the scrollable range. A wrapped slide can be placed right at the track
418
+ // edge, where the rect-derived target may exceed the maximum by a sub-pixel; without clamping
419
+ // the loop would never reach it and never settle (leaving the order normalization undone).
420
+ const maxScrollLeft = viewport.scrollWidth - viewport.clientWidth;
421
+ const target = Math.max(0, Math.min(this.animationTargetLeft, maxScrollLeft));
422
+ const diff = target - current;
423
+ if (Math.abs(diff) < SCROLL_SETTLE_THRESHOLD) {
424
+ viewport.scrollLeft = target;
425
+ this.animationFrameId = null;
426
+ this.endAnimation();
427
+ return;
428
+ }
429
+ viewport.scrollLeft = current + diff * (1 - Math.exp(-dt / SCROLL_SMOOTHING_TAU));
430
+ // The browser can cap `scrollLeft` a sub-pixel short of the computed target (rounding at the
431
+ // scroll boundary). If a frame makes no real progress, treat the animation as settled instead
432
+ // of spinning forever.
433
+ if (Math.abs(viewport.scrollLeft - current) < SCROLL_STALL_THRESHOLD) {
434
+ this.animationFrameId = null;
435
+ this.endAnimation();
436
+ return;
437
+ }
438
+ this.animationFrameId = requestAnimationFrame(time => this.animationFrame(time));
439
+ }
440
+ /** Finalizes the animation: normalizes orders, restores native scrolling and the observer. */
441
+ endAnimation() {
442
+ this.normalizeOrders();
443
+ const viewport = this.viewport().nativeElement;
444
+ viewport.style.scrollSnapType = '';
445
+ viewport.style.scrollBehavior = '';
446
+ this.cdRef.markForCheck();
447
+ this.setupScrollObserver();
448
+ }
449
+ /** Stops the running scroll animation and restores native scrolling, without normalizing. */
450
+ cancelAnimation() {
451
+ if (this.animationFrameId !== null) {
452
+ cancelAnimationFrame(this.animationFrameId);
453
+ this.animationFrameId = null;
454
+ }
455
+ const viewport = this.viewport().nativeElement;
456
+ viewport.style.scrollSnapType = '';
457
+ viewport.style.scrollBehavior = '';
458
+ this.cdRef.markForCheck();
459
+ }
460
+ scheduleAutoPlay() {
461
+ if (this.intervalId) {
462
+ clearInterval(this.intervalId);
463
+ }
464
+ if (!this.autoPlayDuration() || this.items().length === 0 || this.isPaused()) {
465
+ return;
466
+ }
467
+ this.intervalId = setInterval(() => this.next(), this.autoPlayDuration());
468
+ }
469
+ stopAutoPlay() {
470
+ if (this.intervalId) {
471
+ clearInterval(this.intervalId);
472
+ this.intervalId = null;
473
+ }
474
+ }
475
+ setupScrollObserver() {
476
+ if (this.scrollObserver) {
477
+ this.scrollObserver.disconnect();
478
+ }
479
+ const items = this.items();
480
+ if (items.length === 0) {
481
+ return;
482
+ }
483
+ const viewport = this.viewport().nativeElement;
484
+ this.scrollObserver = new IntersectionObserver((entries) => {
485
+ entries.forEach(entry => {
486
+ if (entry.isIntersecting) {
487
+ const target = entry.target;
488
+ const itemIndex = items.findIndex(item => item.elementRef.nativeElement === target);
489
+ if (itemIndex !== -1) {
490
+ this.goToPage(itemIndex, false);
491
+ }
492
+ }
493
+ });
494
+ }, { root: viewport, threshold: 0.6, rootMargin: '0px' });
495
+ for (const item of items) {
496
+ this.scrollObserver.observe(item.elementRef.nativeElement);
497
+ }
498
+ }
499
+ updateEdgeIndices() {
500
+ const total = this.totalPages();
501
+ const current = this.currentPage();
502
+ if (current === null) {
503
+ return;
504
+ }
505
+ if (total <= MAX_PAGES) {
506
+ this.edgeLeftIndex.set(0);
507
+ this.edgeRightIndex.set(total - 1);
508
+ return;
509
+ }
510
+ if (current < this.edgeLeftIndex()) {
511
+ this.edgeLeftIndex.set(current);
512
+ this.edgeRightIndex.set(current + MAX_PAGES - 1);
513
+ }
514
+ if (current > this.edgeRightIndex()) {
515
+ this.edgeRightIndex.set(current);
516
+ this.edgeLeftIndex.set(current - MAX_PAGES + 1);
517
+ }
518
+ }
519
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiCarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
520
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: SiCarouselComponent, isStandalone: true, selector: "si-carousel", inputs: { hidePageControls: { classPropertyName: "hidePageControls", publicName: "hidePageControls", isSignal: true, isRequired: false, transformFunction: null }, autoPlay: { classPropertyName: "autoPlay", publicName: "autoPlay", isSignal: true, isRequired: false, transformFunction: null }, ariaRole: { classPropertyName: "ariaRole", publicName: "ariaRole", isSignal: true, isRequired: false, transformFunction: null }, previousButtonAriaLabel: { classPropertyName: "previousButtonAriaLabel", publicName: "previousButtonAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, nextButtonAriaLabel: { classPropertyName: "nextButtonAriaLabel", publicName: "nextButtonAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, slidePageAriaLabel: { classPropertyName: "slidePageAriaLabel", publicName: "slidePageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, playButtonLabel: { classPropertyName: "playButtonLabel", publicName: "playButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, pauseButtonLabel: { classPropertyName: "pauseButtonLabel", publicName: "pauseButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, carouselRoleDescription: { classPropertyName: "carouselRoleDescription", publicName: "carouselRoleDescription", isSignal: true, isRequired: false, transformFunction: null }, slideRoleDescription: { classPropertyName: "slideRoleDescription", publicName: "slideRoleDescription", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "ariaRole()", "attr.aria-roledescription": "translatedCarouselRoleDescription()", "style.min-width.px": "pageControlContainerMinWidth()" } }, queries: [{ propertyName: "items", predicate: SiCarouselItemDirective, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }, { propertyName: "pageControl", first: true, predicate: ["pageControl"], descendants: true, isSignal: true }, { propertyName: "playPauseBtn", first: true, predicate: ["playPauseBtn"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"carousel-body d-flex flex-grow-1 align-items-center gap-2 min-h-0\">\n <div #viewport class=\"carousel-viewport flex-grow-1 align-self-stretch\" tabindex=\"0\">\n <div class=\"carousel-track h-100\">\n <ng-content />\n </div>\n </div>\n</div>\n@if ((!hidePageControls() || autoPlay()) && totalPages() > 1) {\n <div\n class=\"position-relative d-flex justify-content-center align-items-center mt-4\"\n (siResizeObserver)=\"onResize($event)\"\n >\n @if (!hidePageControls()) {\n <div #pageControl class=\"d-flex align-items-center gap-2\">\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0\"\n [aria-label]=\"previousButtonAriaLabel() | translate\"\n (click)=\"previous()\"\n >\n <si-icon [icon]=\"icons.elementLeft2\"\n /></button>\n <div class=\"d-flex align-items-center\">\n <div\n #dotBtn\n class=\"btn btn-tertiary-ghost btn-icon btn-sm pe-none\"\n [class.opacity-0]=\"totalPages() <= 5\"\n [class.position-absolute]=\"totalPages() <= 5\"\n >\n <span class=\"carousel-pager-small-dot d-block rounded-circle\"></span>\n </div>\n <div\n class=\"d-flex overflow-hidden\"\n [style.width.px]=\"dotBtn.clientWidth * (totalPages() > 5 ? 5 : totalPages())\"\n >\n <div\n class=\"d-flex page-buttons\"\n [style.transform]=\"'translateX(-' + edgeLeftIndex() * dotBtn.clientWidth + 'px)'\"\n >\n @for (page of items(); track page) {\n <button\n type=\"button\"\n class=\"btn btn-tertiary-ghost focus-inside btn-icon btn-sm d-flex align-items-center justify-content-center\"\n [aria-label]=\"\n slidePageAriaLabel() | translate: { page: $index + 1, total: totalPages() }\n \"\n [tabIndex]=\"$index >= edgeLeftIndex() && $index <= edgeRightIndex() ? 0 : -1\"\n [aria-current]=\"currentPage() === $index ? 'true' : 'false'\"\n (click)=\"goToSlide($index)\"\n ><span\n class=\"carousel-pager-dot d-block\"\n [class.active]=\"currentPage() === $index\"\n [class.rounded-circle]=\"currentPage() !== $index\"\n ></span\n ></button>\n }\n </div>\n </div>\n <div\n #dotBtn\n class=\"btn btn-tertiary-ghost btn-icon btn-sm pe-none\"\n [class.opacity-0]=\"totalPages() <= 5\"\n [class.position-absolute]=\"totalPages() <= 5\"\n >\n <span class=\"carousel-pager-small-dot d-block rounded-circle\"></span>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0\"\n [aria-label]=\"nextButtonAriaLabel() | translate\"\n (click)=\"next()\"\n >\n <si-icon [icon]=\"icons.elementRight2\"\n /></button>\n </div>\n }\n\n @if (autoPlay()) {\n <div\n #playPauseBtn\n class=\"position-absolute top-0 end-0\"\n [class.invisible]=\"insufficientSpace()\"\n >\n <button\n type=\"button\"\n class=\"btn btn-tertiary-ghost ms-2\"\n [aria-label]=\"(isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\"\n (click)=\"toggleAutoPlay()\"\n >\n <si-icon class=\"icon\" [icon]=\"isPaused() ? icons.elementPlay : icons.elementPause\" />\n <span aria-hidden=\"true\">{{\n (isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\n }}</span>\n </button>\n </div>\n @if (insufficientSpace()) {\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0 align-items-center position-absolute top-0 end-0 ms-2\"\n [aria-label]=\"(isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\"\n (click)=\"toggleAutoPlay()\"\n >\n <si-icon [icon]=\"isPaused() ? icons.elementPlay : icons.elementPause\" />\n </button>\n }\n }\n </div>\n}\n", styles: [":host{--si-carousel-gap: 16px;display:flex;flex-direction:column;flex:1 1 0}.carousel-viewport{min-block-size:0;overflow-y:hidden;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}.page-buttons{transition:transform calc(.5s * var(--element-animations-enabled, 1)) ease}.carousel-track{display:flex;gap:var(--si-carousel-gap)}.carousel-pager-dot{inline-size:.375rem;block-size:.375rem;background-color:var(--element-ui-3);transition:background-color calc(.5s * var(--element-animations-enabled, 1)) ease}.carousel-pager-dot.active{transition:inline-size calc(.5s * var(--element-animations-enabled, 1)) ease,background-color calc(.5s * var(--element-animations-enabled, 1)) ease;inline-size:.75rem;background-color:var(--element-ui-0);border-radius:6.25rem}.carousel-pager-small-dot{background-color:var(--element-ui-3);inline-size:.25rem;block-size:.25rem}\n"], dependencies: [{ kind: "directive", type: SiResizeObserverDirective, selector: "[siResizeObserver]", inputs: ["resizeThrottle", "emitInitial"], outputs: ["siResizeObserver"] }, { kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
521
+ }
522
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiCarouselComponent, decorators: [{
523
+ type: Component,
524
+ args: [{ selector: 'si-carousel', imports: [SiTranslatePipe, SiResizeObserverDirective, SiIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
525
+ '[attr.role]': 'ariaRole()',
526
+ '[attr.aria-roledescription]': 'translatedCarouselRoleDescription()',
527
+ '[style.min-width.px]': 'pageControlContainerMinWidth()'
528
+ }, template: "<div class=\"carousel-body d-flex flex-grow-1 align-items-center gap-2 min-h-0\">\n <div #viewport class=\"carousel-viewport flex-grow-1 align-self-stretch\" tabindex=\"0\">\n <div class=\"carousel-track h-100\">\n <ng-content />\n </div>\n </div>\n</div>\n@if ((!hidePageControls() || autoPlay()) && totalPages() > 1) {\n <div\n class=\"position-relative d-flex justify-content-center align-items-center mt-4\"\n (siResizeObserver)=\"onResize($event)\"\n >\n @if (!hidePageControls()) {\n <div #pageControl class=\"d-flex align-items-center gap-2\">\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0\"\n [aria-label]=\"previousButtonAriaLabel() | translate\"\n (click)=\"previous()\"\n >\n <si-icon [icon]=\"icons.elementLeft2\"\n /></button>\n <div class=\"d-flex align-items-center\">\n <div\n #dotBtn\n class=\"btn btn-tertiary-ghost btn-icon btn-sm pe-none\"\n [class.opacity-0]=\"totalPages() <= 5\"\n [class.position-absolute]=\"totalPages() <= 5\"\n >\n <span class=\"carousel-pager-small-dot d-block rounded-circle\"></span>\n </div>\n <div\n class=\"d-flex overflow-hidden\"\n [style.width.px]=\"dotBtn.clientWidth * (totalPages() > 5 ? 5 : totalPages())\"\n >\n <div\n class=\"d-flex page-buttons\"\n [style.transform]=\"'translateX(-' + edgeLeftIndex() * dotBtn.clientWidth + 'px)'\"\n >\n @for (page of items(); track page) {\n <button\n type=\"button\"\n class=\"btn btn-tertiary-ghost focus-inside btn-icon btn-sm d-flex align-items-center justify-content-center\"\n [aria-label]=\"\n slidePageAriaLabel() | translate: { page: $index + 1, total: totalPages() }\n \"\n [tabIndex]=\"$index >= edgeLeftIndex() && $index <= edgeRightIndex() ? 0 : -1\"\n [aria-current]=\"currentPage() === $index ? 'true' : 'false'\"\n (click)=\"goToSlide($index)\"\n ><span\n class=\"carousel-pager-dot d-block\"\n [class.active]=\"currentPage() === $index\"\n [class.rounded-circle]=\"currentPage() !== $index\"\n ></span\n ></button>\n }\n </div>\n </div>\n <div\n #dotBtn\n class=\"btn btn-tertiary-ghost btn-icon btn-sm pe-none\"\n [class.opacity-0]=\"totalPages() <= 5\"\n [class.position-absolute]=\"totalPages() <= 5\"\n >\n <span class=\"carousel-pager-small-dot d-block rounded-circle\"></span>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0\"\n [aria-label]=\"nextButtonAriaLabel() | translate\"\n (click)=\"next()\"\n >\n <si-icon [icon]=\"icons.elementRight2\"\n /></button>\n </div>\n }\n\n @if (autoPlay()) {\n <div\n #playPauseBtn\n class=\"position-absolute top-0 end-0\"\n [class.invisible]=\"insufficientSpace()\"\n >\n <button\n type=\"button\"\n class=\"btn btn-tertiary-ghost ms-2\"\n [aria-label]=\"(isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\"\n (click)=\"toggleAutoPlay()\"\n >\n <si-icon class=\"icon\" [icon]=\"isPaused() ? icons.elementPlay : icons.elementPause\" />\n <span aria-hidden=\"true\">{{\n (isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\n }}</span>\n </button>\n </div>\n @if (insufficientSpace()) {\n <button\n type=\"button\"\n class=\"btn btn-icon btn-tertiary-ghost flex-shrink-0 align-items-center position-absolute top-0 end-0 ms-2\"\n [aria-label]=\"(isPaused() ? playButtonLabel() : pauseButtonLabel()) | translate\"\n (click)=\"toggleAutoPlay()\"\n >\n <si-icon [icon]=\"isPaused() ? icons.elementPlay : icons.elementPause\" />\n </button>\n }\n }\n </div>\n}\n", styles: [":host{--si-carousel-gap: 16px;display:flex;flex-direction:column;flex:1 1 0}.carousel-viewport{min-block-size:0;overflow-y:hidden;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none}.page-buttons{transition:transform calc(.5s * var(--element-animations-enabled, 1)) ease}.carousel-track{display:flex;gap:var(--si-carousel-gap)}.carousel-pager-dot{inline-size:.375rem;block-size:.375rem;background-color:var(--element-ui-3);transition:background-color calc(.5s * var(--element-animations-enabled, 1)) ease}.carousel-pager-dot.active{transition:inline-size calc(.5s * var(--element-animations-enabled, 1)) ease,background-color calc(.5s * var(--element-animations-enabled, 1)) ease;inline-size:.75rem;background-color:var(--element-ui-0);border-radius:6.25rem}.carousel-pager-small-dot{background-color:var(--element-ui-3);inline-size:.25rem;block-size:.25rem}\n"] }]
529
+ }], ctorParameters: () => [], propDecorators: { hidePageControls: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidePageControls", required: false }] }], autoPlay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoPlay", required: false }] }], ariaRole: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaRole", required: false }] }], previousButtonAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousButtonAriaLabel", required: false }] }], nextButtonAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextButtonAriaLabel", required: false }] }], slidePageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidePageAriaLabel", required: false }] }], playButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "playButtonLabel", required: false }] }], pauseButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseButtonLabel", required: false }] }], carouselRoleDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "carouselRoleDescription", required: false }] }], slideRoleDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideRoleDescription", required: false }] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SiCarouselItemDirective), { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }], pageControl: [{ type: i0.ViewChild, args: ['pageControl', { isSignal: true }] }], playPauseBtn: [{ type: i0.ViewChild, args: ['playPauseBtn', { isSignal: true }] }] } });
530
+
531
+ /**
532
+ * Copyright (c) Siemens 2016 - 2026
533
+ * SPDX-License-Identifier: MIT
534
+ */
535
+
536
+ /**
537
+ * Generated bundle index. Do not edit.
538
+ */
539
+
540
+ export { SiCarouselComponent, SiCarouselItemDirective };
541
+ //# sourceMappingURL=siemens-element-ng-carousel.mjs.map