@tedi-design-system/angular 6.2.0-rc.5 → 6.2.0-rc.7
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.
- package/community/components/tags/status-badge/status-badge.component.d.ts +3 -0
- package/community/components/tags/status-badge/status-badge.component.d.ts.map +1 -1
- package/fesm2022/tedi-design-system-angular-community.mjs +3 -0
- package/fesm2022/tedi-design-system-angular-community.mjs.map +1 -1
- package/fesm2022/tedi-design-system-angular-tedi.mjs +64 -6
- package/fesm2022/tedi-design-system-angular-tedi.mjs.map +1 -1
- package/package.json +1 -1
- package/tedi/components/content/carousel/carousel-content/carousel-content.component.d.ts +22 -1
- package/tedi/components/content/carousel/carousel-content/carousel-content.component.d.ts.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, signal, inject, ElementRef, Directive, Injectable, InjectionToken, REQUEST, PLATFORM_ID, effect, isSignal, Pipe, model, output, Injector, Renderer2, HostListener, viewChild, contentChild, contentChildren, forwardRef, ViewChild, TemplateRef, HostBinding, Attribute, ViewContainerRef, runInInjectionContext, ContentChildren, afterNextRender, ContentChild, makeEnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { input, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, signal, inject, ElementRef, Directive, Injectable, InjectionToken, REQUEST, PLATFORM_ID, effect, isSignal, Pipe, model, output, Injector, Renderer2, HostListener, viewChild, contentChild, contentChildren, forwardRef, ViewChild, TemplateRef, viewChildren, HostBinding, Attribute, ViewContainerRef, runInInjectionContext, ContentChildren, afterNextRender, ContentChild, makeEnvironmentProviders } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/cdk/layout';
|
|
4
4
|
import { DOCUMENT, isPlatformBrowser, isPlatformServer, NgTemplateOutlet, NgClass, NgFor, NgIf } from '@angular/common';
|
|
5
5
|
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
|
|
@@ -4254,7 +4254,9 @@ class CarouselContentComponent {
|
|
|
4254
4254
|
translationService = inject(TediTranslationService);
|
|
4255
4255
|
breakpointService = inject(BreakpointService);
|
|
4256
4256
|
host = inject(ElementRef);
|
|
4257
|
+
liveAnnouncer = inject(LiveAnnouncer);
|
|
4257
4258
|
track = viewChild.required("track");
|
|
4259
|
+
slideElements = viewChildren("slide");
|
|
4258
4260
|
slides = contentChildren(CarouselSlideDirective);
|
|
4259
4261
|
trackIndex = signal(0);
|
|
4260
4262
|
animate = signal(false);
|
|
@@ -4321,6 +4323,15 @@ class CarouselContentComponent {
|
|
|
4321
4323
|
renderedActiveIndex = computed(() => {
|
|
4322
4324
|
return this.trackIndex() - this.windowBase() + this.buffer();
|
|
4323
4325
|
});
|
|
4326
|
+
/**
|
|
4327
|
+
* Checks if a slide at the given rendered index is currently visible in the viewport.
|
|
4328
|
+
* Used to determine which slides should be accessible to screen readers.
|
|
4329
|
+
*/
|
|
4330
|
+
isSlideVisible(renderedIndex) {
|
|
4331
|
+
const activeIndex = this.renderedActiveIndex();
|
|
4332
|
+
const slidesPerView = Math.ceil(this.currentSlidesPerView());
|
|
4333
|
+
return renderedIndex >= activeIndex && renderedIndex < activeIndex + slidesPerView;
|
|
4334
|
+
}
|
|
4324
4335
|
renderedIndices = computed(() => {
|
|
4325
4336
|
const slidesCount = this.slides().length;
|
|
4326
4337
|
if (!slidesCount) {
|
|
@@ -4370,11 +4381,17 @@ class CarouselContentComponent {
|
|
|
4370
4381
|
});
|
|
4371
4382
|
locked = false;
|
|
4372
4383
|
dragging = false;
|
|
4384
|
+
pendingFocus = false;
|
|
4373
4385
|
startX = 0;
|
|
4374
4386
|
startIndex = 0;
|
|
4375
4387
|
ro;
|
|
4376
4388
|
wheelTimeout;
|
|
4377
4389
|
scrollDelta = 0;
|
|
4390
|
+
onScroll() {
|
|
4391
|
+
// Prevent any scroll triggered by focus (e.g., VoiceOver navigation)
|
|
4392
|
+
this.host.nativeElement.scrollLeft = 0;
|
|
4393
|
+
this.host.nativeElement.scrollTop = 0;
|
|
4394
|
+
}
|
|
4378
4395
|
onWheel(event) {
|
|
4379
4396
|
const slidesCount = this.slides().length;
|
|
4380
4397
|
if (!slidesCount) {
|
|
@@ -4508,6 +4525,7 @@ class CarouselContentComponent {
|
|
|
4508
4525
|
this.animate.set(true);
|
|
4509
4526
|
this.trackIndex.update((i) => i + 1);
|
|
4510
4527
|
this.lockNavigation();
|
|
4528
|
+
this.announceSlideChange();
|
|
4511
4529
|
}
|
|
4512
4530
|
prev() {
|
|
4513
4531
|
if (!this.slides().length || this.locked) {
|
|
@@ -4516,8 +4534,9 @@ class CarouselContentComponent {
|
|
|
4516
4534
|
this.animate.set(true);
|
|
4517
4535
|
this.trackIndex.update((i) => i - 1);
|
|
4518
4536
|
this.lockNavigation();
|
|
4537
|
+
this.announceSlideChange();
|
|
4519
4538
|
}
|
|
4520
|
-
goToIndex(index) {
|
|
4539
|
+
goToIndex(index, options) {
|
|
4521
4540
|
const slidesCount = this.slides().length;
|
|
4522
4541
|
if (!slidesCount || this.locked) {
|
|
4523
4542
|
return;
|
|
@@ -4527,6 +4546,26 @@ class CarouselContentComponent {
|
|
|
4527
4546
|
const delta = normalized - current;
|
|
4528
4547
|
this.animate.set(true);
|
|
4529
4548
|
this.trackIndex.update((i) => i + delta);
|
|
4549
|
+
if (options?.focusSlide) {
|
|
4550
|
+
// Focus after transition completes so DOM positions are stable
|
|
4551
|
+
this.pendingFocus = true;
|
|
4552
|
+
}
|
|
4553
|
+
else {
|
|
4554
|
+
this.announceSlideChange();
|
|
4555
|
+
}
|
|
4556
|
+
}
|
|
4557
|
+
/**
|
|
4558
|
+
* Focuses the currently active slide for screen reader users.
|
|
4559
|
+
* Uses preventScroll to avoid breaking carousel layout.
|
|
4560
|
+
*/
|
|
4561
|
+
focusActiveSlide() {
|
|
4562
|
+
setTimeout(() => {
|
|
4563
|
+
const activeIndex = this.renderedActiveIndex();
|
|
4564
|
+
const slideElement = this.slideElements()[activeIndex];
|
|
4565
|
+
if (slideElement) {
|
|
4566
|
+
slideElement.nativeElement.focus({ preventScroll: true });
|
|
4567
|
+
}
|
|
4568
|
+
});
|
|
4530
4569
|
}
|
|
4531
4570
|
onTransitionEnd(e) {
|
|
4532
4571
|
if (e.target !== this.track().nativeElement ||
|
|
@@ -4536,13 +4575,29 @@ class CarouselContentComponent {
|
|
|
4536
4575
|
}
|
|
4537
4576
|
this.animate.set(false);
|
|
4538
4577
|
this.windowBase.set(Math.floor(this.trackIndex()));
|
|
4578
|
+
if (this.pendingFocus) {
|
|
4579
|
+
this.pendingFocus = false;
|
|
4580
|
+
this.focusActiveSlide();
|
|
4581
|
+
}
|
|
4539
4582
|
}
|
|
4540
4583
|
lockNavigation() {
|
|
4541
4584
|
this.locked = true;
|
|
4542
4585
|
setTimeout(() => (this.locked = false), this.transitionMs());
|
|
4543
4586
|
}
|
|
4587
|
+
/**
|
|
4588
|
+
* Announces the current slide position to screen readers via LiveAnnouncer.
|
|
4589
|
+
* Called after navigation to inform users of the slide change.
|
|
4590
|
+
*/
|
|
4591
|
+
announceSlideChange() {
|
|
4592
|
+
setTimeout(() => {
|
|
4593
|
+
const slideNumber = this.slideIndex() + 1;
|
|
4594
|
+
const totalSlides = this.slides().length;
|
|
4595
|
+
const message = this.translationService.translate("carousel.slide", slideNumber, totalSlides);
|
|
4596
|
+
this.liveAnnouncer.announce(message, "polite");
|
|
4597
|
+
}, 100);
|
|
4598
|
+
}
|
|
4544
4599
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CarouselContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4545
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: CarouselContentComponent, isStandalone: true, selector: "tedi-carousel-content", inputs: { slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, fade: { classPropertyName: "fade", publicName: "fade", isSignal: true, isRequired: false, transformFunction: null }, transitionMs: { classPropertyName: "transitionMs", publicName: "transitionMs", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "0", "role": "region", "aria-roledescription": "carousel", "aria-live": "off" }, listeners: { "wheel": "onWheel($event)", "keydown": "onKeyDown($event)", "pointerdown": "onPointerDown($event)", "pointermove": "onPointerMove($event)", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "lostpointercapture": "onPointerUp()" }, properties: { "attr.aria-label": "translationService.track('carousel')()", "class": "classes()" } }, queries: [{ propertyName: "slides", predicate: CarouselSlideDirective, isSignal: true }], viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n class=\"tedi-carousel__slide\"\n [attr.role]=\"$index
|
|
4600
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: CarouselContentComponent, isStandalone: true, selector: "tedi-carousel-content", inputs: { slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, fade: { classPropertyName: "fade", publicName: "fade", isSignal: true, isRequired: false, transformFunction: null }, transitionMs: { classPropertyName: "transitionMs", publicName: "transitionMs", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "0", "role": "region", "aria-roledescription": "carousel", "aria-live": "off" }, listeners: { "scroll": "onScroll()", "wheel": "onWheel($event)", "keydown": "onKeyDown($event)", "pointerdown": "onPointerDown($event)", "pointermove": "onPointerMove($event)", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()", "lostpointercapture": "onPointerUp()" }, properties: { "attr.aria-label": "translationService.track('carousel')()", "class": "classes()" } }, queries: [{ propertyName: "slides", predicate: CarouselSlideDirective, isSignal: true }], viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, isSignal: true }, { propertyName: "slideElements", predicate: ["slide"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n #slide\n class=\"tedi-carousel__slide\"\n [attr.role]=\"isSlideVisible($index) ? 'group' : 'presentation'\"\n aria-roledescription=\"slide\"\n [attr.aria-label]=\"\n translationService.track('carousel.slide', idx + 1, slides().length)()\n \"\n [attr.aria-current]=\"$index === renderedActiveIndex() ? 'true' : null\"\n [attr.aria-hidden]=\"isSlideVisible($index) ? null : 'true'\"\n [attr.tabindex]=\"isSlideVisible($index) ? '-1' : null\"\n [style.flex]=\"slideFlex()\"\n >\n <ng-container *ngTemplateOutlet=\"slides()[idx].template\"></ng-container>\n </div>\n }\n</div>\n", styles: [".tedi-carousel__content{position:relative;width:100%;overflow:hidden;overscroll-behavior:contain;touch-action:pan-y;cursor:grab}.tedi-carousel__content:focus-visible{outline:var(--borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--borders-03))}.tedi-carousel__content:active{cursor:grabbing}.tedi-carousel__content--fade-right{mask-image:linear-gradient(to right,black 90%,transparent 100%)}.tedi-carousel__content--fade-x{mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);mask-composite:intersect}.tedi-carousel__track{display:flex;will-change:transform}.tedi-carousel__slide{-webkit-user-select:none;user-select:none;scroll-snap-align:none;scroll-margin:0;-webkit-user-drag:none}.tedi-carousel__slide:focus{outline:none}.tedi-carousel__slide:focus-visible{outline:var(--borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--borders-03))}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4546
4601
|
}
|
|
4547
4602
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CarouselContentComponent, decorators: [{
|
|
4548
4603
|
type: Component,
|
|
@@ -4553,8 +4608,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
|
|
|
4553
4608
|
"[attr.aria-label]": "translationService.track('carousel')()",
|
|
4554
4609
|
"aria-live": "off",
|
|
4555
4610
|
"[class]": "classes()",
|
|
4556
|
-
}, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n class=\"tedi-carousel__slide\"\n [attr.role]=\"$index
|
|
4557
|
-
}], propDecorators: {
|
|
4611
|
+
}, template: "<div\n #track\n class=\"tedi-carousel__track\"\n [style]=\"trackStyle()\"\n (transitionend)=\"onTransitionEnd($event)\"\n>\n @for (idx of renderedIndices(); track $index) {\n <div\n #slide\n class=\"tedi-carousel__slide\"\n [attr.role]=\"isSlideVisible($index) ? 'group' : 'presentation'\"\n aria-roledescription=\"slide\"\n [attr.aria-label]=\"\n translationService.track('carousel.slide', idx + 1, slides().length)()\n \"\n [attr.aria-current]=\"$index === renderedActiveIndex() ? 'true' : null\"\n [attr.aria-hidden]=\"isSlideVisible($index) ? null : 'true'\"\n [attr.tabindex]=\"isSlideVisible($index) ? '-1' : null\"\n [style.flex]=\"slideFlex()\"\n >\n <ng-container *ngTemplateOutlet=\"slides()[idx].template\"></ng-container>\n </div>\n }\n</div>\n", styles: [".tedi-carousel__content{position:relative;width:100%;overflow:hidden;overscroll-behavior:contain;touch-action:pan-y;cursor:grab}.tedi-carousel__content:focus-visible{outline:var(--borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--borders-03))}.tedi-carousel__content:active{cursor:grabbing}.tedi-carousel__content--fade-right{mask-image:linear-gradient(to right,black 90%,transparent 100%)}.tedi-carousel__content--fade-x{mask-image:linear-gradient(to right,black 85%,transparent 100%),linear-gradient(to left,black 85%,transparent 100%);mask-composite:intersect}.tedi-carousel__track{display:flex;will-change:transform}.tedi-carousel__slide{-webkit-user-select:none;user-select:none;scroll-snap-align:none;scroll-margin:0;-webkit-user-drag:none}.tedi-carousel__slide:focus{outline:none}.tedi-carousel__slide:focus-visible{outline:var(--borders-02) solid var(--tedi-primary-500);outline-offset:calc(-1 * var(--borders-03))}\n"] }]
|
|
4612
|
+
}], propDecorators: { onScroll: [{
|
|
4613
|
+
type: HostListener,
|
|
4614
|
+
args: ["scroll"]
|
|
4615
|
+
}], onWheel: [{
|
|
4558
4616
|
type: HostListener,
|
|
4559
4617
|
args: ["wheel", ["$event"]]
|
|
4560
4618
|
}], onKeyDown: [{
|
|
@@ -4624,7 +4682,7 @@ class CarouselIndicatorsComponent {
|
|
|
4624
4682
|
this.carousel.carouselContent().prev();
|
|
4625
4683
|
}
|
|
4626
4684
|
handleIndicatorClick(index) {
|
|
4627
|
-
this.carousel.carouselContent().goToIndex(index);
|
|
4685
|
+
this.carousel.carouselContent().goToIndex(index, { focusSlide: true });
|
|
4628
4686
|
}
|
|
4629
4687
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: CarouselIndicatorsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4630
4688
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: CarouselIndicatorsComponent, isStandalone: true, selector: "tedi-carousel-indicators", inputs: { withArrows: { classPropertyName: "withArrows", publicName: "withArrows", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveBack')()\"\n (click)=\"handlePrev()\"\n >\n <tedi-icon name=\"arrow_back\" [size]=\"18\" />\n </button>\n}\n\n@if (variant() === \"dots\") {\n @for (indicator of indicatorsArray(); track indicator.index) {\n <button\n type=\"button\"\n class=\"tedi-carousel__indicator\"\n [attr.aria-label]=\"\n translationService.track('carousel.showSlide', indicator.index + 1)()\n \"\n [ngClass]=\"indicator.active ? 'tedi-carousel__indicator--active' : null\"\n (click)=\"handleIndicatorClick(indicator.index)\"\n ></button>\n }\n} @else if (activeSlideNumber()) {\n <div>\n <b tedi-text color=\"brand\">{{ activeSlideNumber() }}</b>\n <span tedi-text color=\"tertiary\"> / {{ indicatorsArray().length }}</span>\n </div>\n}\n\n@if (withArrows()) {\n <button\n tedi-button\n type=\"button\"\n variant=\"neutral\"\n [attr.aria-label]=\"translationService.track('carousel.moveForward')()\"\n (click)=\"handleNext()\"\n >\n <tedi-icon name=\"arrow_forward\" [size]=\"18\" />\n </button>\n}\n", styles: ["tedi-carousel-indicators{display:flex;gap:var(--layout-grid-gutters-04);align-items:center;min-height:24px}.tedi-carousel__indicator{position:relative;width:24px;height:24px;cursor:pointer;background:none;border:none}.tedi-carousel__indicator:after{position:absolute;top:50%;left:50%;width:22px;height:8px;content:\"\";background-color:transparent;border:1px solid var(--tedi-primary-600);border-radius:100px;transform:translate(-50%,-50%)}.tedi-carousel__indicator:hover:after{border-color:var(--tedi-primary-700)}.tedi-carousel__indicator:active:after{background-color:var(--tedi-primary-800);border-color:var(--tedi-primary-800)}.tedi-carousel__indicator:focus-visible:after{outline:var(--borders-02) solid var(--tedi-primary-500);outline-offset:var(--borders-01)}.tedi-carousel__indicator--active:after{background-color:var(--tedi-primary-600)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonComponent, selector: "[tedi-button]", inputs: ["variant", "size"] }, { kind: "component", type: IconComponent, selector: "tedi-icon", inputs: ["name", "size", "color", "background", "variant", "type", "label"] }, { kind: "component", type: TextComponent, selector: "[tedi-text]", inputs: ["modifiers", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|