diff --git a/projects/igniteui-angular/carousel/src/carousel/carousel.component.ts b/projects/igniteui-angular/carousel/src/carousel/carousel.component.ts index c7c27892c08..ae88268ca89 100644 --- a/projects/igniteui-angular/carousel/src/carousel/carousel.component.ts +++ b/projects/igniteui-angular/carousel/src/carousel/carousel.component.ts @@ -1,9 +1,9 @@ import { NgClass, NgTemplateOutlet } from '@angular/common'; -import { AfterContentInit, Component, ContentChild, ContentChildren, ElementRef, EventEmitter, HostBinding, HostListener, Injectable, Input, IterableChangeRecord, IterableDiffer, IterableDiffers, OnDestroy, Output, QueryList, TemplateRef, ViewChild, ViewChildren, booleanAttribute, DOCUMENT, inject } from '@angular/core'; +import { AfterContentInit, Component, ContentChild, ContentChildren, ElementRef, EventEmitter, HostBinding, HostListener, Injectable, Input, IterableChangeRecord, IterableDiffer, IterableDiffers, OnDestroy, Output, QueryList, TemplateRef, ViewChild, ViewChildren, booleanAttribute, inject } from '@angular/core'; import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser'; import { merge, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { CarouselResourceStringsEN, ICarouselResourceStrings, ɵIgxDirectionality } from 'igniteui-angular/core'; +import { CarouselResourceStringsEN, ICarouselResourceStrings, isLeftToRight} from 'igniteui-angular/core'; import { first, IBaseEventArgs, last, PlatformUtil } from 'igniteui-angular/core'; import { CarouselAnimationDirection, IgxCarouselComponentBase } from './carousel-base'; import { IgxCarouselIndicatorDirective, IgxCarouselNextButtonDirective, IgxCarouselPrevButtonDirective } from './carousel.directives'; @@ -64,8 +64,7 @@ export class IgxCarouselComponent extends IgxCarouselComponentBase implements On private element = inject(ElementRef); private iterableDiffers = inject(IterableDiffers); private platformUtil = inject(PlatformUtil); - private dir = inject(ɵIgxDirectionality); - private document = inject(DOCUMENT); + /** @@ -725,21 +724,22 @@ export class IgxCarouselComponent extends IgxCarouselComponentBase implements On public handleKeydown(event: KeyboardEvent): void { const { key } = event; const slides = this.slides.toArray(); + const isRTL = !isLeftToRight(this.nativeElement); switch (key) { case this.platformUtil.KEYMAP.ARROW_LEFT: - this.dir.rtl ? this.next() : this.prev(); + isRTL ? this.next() : this.prev(); break; case this.platformUtil.KEYMAP.ARROW_RIGHT: - this.dir.rtl ? this.prev() : this.next(); + isRTL ? this.prev() : this.next(); break; case this.platformUtil.KEYMAP.HOME: event.preventDefault(); - this.select(this.dir.rtl ? last(slides) : first(slides)); + this.select(isRTL ? last(slides) : first(slides)); break; case this.platformUtil.KEYMAP.END: event.preventDefault(); - this.select(this.dir.rtl ? first(slides) : last(slides)); + this.select(isRTL ? first(slides) : last(slides)); break; } diff --git a/projects/igniteui-angular/core/src/core/utils.ts b/projects/igniteui-angular/core/src/core/utils.ts index 6f9a0c7b2d6..97adfb1b9e6 100644 --- a/projects/igniteui-angular/core/src/core/utils.ts +++ b/projects/igniteui-angular/core/src/core/utils.ts @@ -8,6 +8,16 @@ import type { IgxTheme } from '../services/theme/theme.token'; /** @hidden @internal */ export const ELEMENTS_TOKEN = /*@__PURE__*/new InjectionToken('elements environment'); + +/** + * Returns true if the element's direction is left-to-right + * + * @hidden @internal + */ +export function isLeftToRight(element: Element): boolean { + return element?.matches(':dir(ltr)') ?? true; +} + /** * @hidden */ diff --git a/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts b/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts deleted file mode 100644 index ad29ace4c56..00000000000 --- a/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { TestBed, inject, waitForAsync } from '@angular/core/testing'; -import { Component, DOCUMENT, inject as inject_1 } from '@angular/core'; -import { IgxDirectionality, DIR_DOCUMENT } from './directionality'; - -interface FakeDoc { - body: { dir?: string }; - documentElement: { dir?: string }; -} - -describe('IgxDirectionality', () => { - describe('DI', () => { - beforeEach(waitForAsync(() => - TestBed.configureTestingModule({ - imports: [InjectsIgxDirectionalityComponent] - }).compileComponents() - )); - - it('should inject the document through the injectionToken properly', () => { - const injectionToken = TestBed.inject(DIR_DOCUMENT); - const document = TestBed.inject(DOCUMENT); - - expect(injectionToken).toEqual(document); - expect(injectionToken).toEqual(jasmine.any(Document)); - expect(document).toBeTruthy(jasmine.any(Document)); - }); - - it('should read dir from html if not specified on the body', inject([DOCUMENT], () => { - const fixture = TestBed.createComponent(InjectsIgxDirectionalityComponent); - const component = fixture.debugElement.componentInstance; - - expect(component.dir.document).not.toBeNull(); - expect(component.dir.document).not.toBeUndefined(); - expect(component.dir.document).toEqual(jasmine.any(Document)); - })); - - }); - - describe('RLT, LTR', () => { - let fakeDoc: FakeDoc; - - let expectedRes: string; - let dirInstance: IgxDirectionality; - - beforeEach(() => { - fakeDoc = { body: {}, documentElement: {} }; - - TestBed.configureTestingModule({ - providers: [ - { provide: DOCUMENT, useValue: fakeDoc }, - IgxDirectionality - ] - }); - }); - it('should read dir from html if not specified on the body', () => { - expectedRes = 'rtl'; - fakeDoc.documentElement.dir = expectedRes; - - dirInstance = TestBed.inject(IgxDirectionality); - expect(dirInstance.value).toEqual(expectedRes); - }); - it('should read dir from body even it is also specified on the html element', () => { - fakeDoc.documentElement.dir = 'ltr'; - expectedRes = 'rtl'; - fakeDoc.body.dir = expectedRes; - - dirInstance = TestBed.inject(IgxDirectionality); - expect(dirInstance.value).toEqual(expectedRes); - }); - - it('should default to ltr if nothing specified', () => { - expectedRes = 'ltr'; - - dirInstance = TestBed.inject(IgxDirectionality); - expect(dirInstance.value).toEqual(expectedRes); - }); - - it('should default to ltr if invalid values are set both on body or html elements', () => { - fakeDoc.documentElement.dir = 'none'; - fakeDoc.body.dir = 'irrelevant'; - - dirInstance = TestBed.inject(IgxDirectionality); - expect(dirInstance.value).toEqual('ltr'); - }); - }); -}); - -@Component({ - selector: 'igx-div-element', - template: ` -
element
- `, - standalone: true -}) -class InjectsIgxDirectionalityComponent { - public dir = inject_1(IgxDirectionality); -} diff --git a/projects/igniteui-angular/core/src/services/direction/directionality.ts b/projects/igniteui-angular/core/src/services/direction/directionality.ts deleted file mode 100644 index 6c7726caf40..00000000000 --- a/projects/igniteui-angular/core/src/services/direction/directionality.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Injectable, InjectionToken, inject, DOCUMENT } from '@angular/core'; - -/** - * @hidden @internal - */ -export type Direction = 'ltr' | 'rtl'; - -/** - * @hidden - */ -function DIR_DOCUMENT_FACTORY(): Document { - return inject(DOCUMENT); -} - -/** - * Injection token is used to inject the document into Directionality - * which factory could be faked for testing purposes. - * - * We can't provide and mock the DOCUMENT token from platform-browser because configureTestingModule - * allows override of the default providers, directive, pipes, modules of the test injector - * which causes errors. - * - * @hidden @internal - */ -export const DIR_DOCUMENT = /*@__PURE__*/new InjectionToken('dir-doc', { - providedIn: 'root', - factory: DIR_DOCUMENT_FACTORY -}); - -/** - * @hidden @internal - * - * Bidirectional service that extracts the value of the direction attribute on the body or html elements. - * - * The dir attribute over the body element takes precedence. - */ -@Injectable({ - providedIn: 'root' -}) -export class IgxDirectionality { - private _dir: Direction; - private _document: Document; - - public get value(): Direction { - return this._dir; - } - - public get document() { - return this._document; - } - - public get rtl() { - return this._dir === 'rtl'; - } - - constructor() { - const document = inject(DIR_DOCUMENT); - - this._document = document; - const bodyDir = this._document.body ? this._document.body.dir : null; - const htmlDir = this._document.documentElement ? this._document.documentElement.dir : null; - const extractedDir = bodyDir || htmlDir; - this._dir = (extractedDir === 'ltr' || extractedDir === 'rtl') ? extractedDir : 'ltr'; - } -} diff --git a/projects/igniteui-angular/core/src/services/public_api.ts b/projects/igniteui-angular/core/src/services/public_api.ts index 69ae76e9358..b28bfa2eff6 100644 --- a/projects/igniteui-angular/core/src/services/public_api.ts +++ b/projects/igniteui-angular/core/src/services/public_api.ts @@ -2,7 +2,6 @@ export * from './animation/angular-animation-player'; export * from './animation/angular-animation-service'; export * from './animation/animation'; -export { Direction as ɵDirection, DIR_DOCUMENT as ɵDIR_DOCUMENT, IgxDirectionality as ɵIgxDirectionality } from './direction/directionality'; export * from './overlay/overlay'; export * from './overlay/position'; export * from './overlay/scroll'; diff --git a/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.ts b/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.ts index 8fb9c40cc14..134aeae958f 100644 --- a/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.ts +++ b/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.ts @@ -12,12 +12,13 @@ import { booleanAttribute, effect, signal, - inject + inject, + ElementRef } from '@angular/core'; import { ControlValueAccessor, NgControl, Validators } from '@angular/forms'; import { fromEvent, noop, Subject, takeUntil } from 'rxjs'; import { IgxRadioComponent } from '../radio.component'; -import { ɵIgxDirectionality } from 'igniteui-angular/core'; +import { isLeftToRight } from 'igniteui-angular/core'; import { IChangeCheckboxEventArgs } from 'igniteui-angular/directives'; /** * Determines the Radio Group alignment @@ -60,8 +61,8 @@ let nextId = 0; }) export class IgxRadioGroupDirective implements ControlValueAccessor, OnDestroy, DoCheck { public ngControl = inject(NgControl, { optional: true, self: true }); - private _directionality = inject(ɵIgxDirectionality); private cdr = inject(ChangeDetectorRef); + private readonly _element = inject>(ElementRef); private _radioButtons = signal([]); private _radioButtonsList = new QueryList(); @@ -259,7 +260,7 @@ export class IgxRadioGroupDirective implements ControlValueAccessor, OnDestroy, if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key)) { let index = checked ? buttons.indexOf(checked) : -1; - const ltr = this._directionality.value === 'ltr'; + const ltr = isLeftToRight(this._element.nativeElement); switch (key) { case 'ArrowUp': diff --git a/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts b/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts index 4838a1e45ba..5eaca31005c 100644 --- a/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts +++ b/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts @@ -3,7 +3,6 @@ import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angul import { FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms'; import { By, HammerModule } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { ɵDIR_DOCUMENT, ɵIgxDirectionality } from 'igniteui-angular/core'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { IgxSliderType, IgxThumbFromTemplateDirective, IgxThumbToTemplateDirective, IRangeSliderValue, TickLabelsOrientation, TicksOrientation } from './slider.common'; import { IgxSliderComponent } from './slider.component'; @@ -24,16 +23,8 @@ const SLIDER_TICK_LABELS_HIDDEN_CLASS = 'igx-slider__tick-label--hidden'; const TOP_TO_BOTTOM_TICK_LABLES = '.igx-slider__tick-labels--top-bottom'; const BOTTOM_TO_TOP_TICK_LABLES = '.igx-slider__tick-labels--bottom-top'; -interface FakeDoc { - body: { dir?: string }; - documentElement: { dir?: string }; -} - describe('IgxSlider', () => { - let fakeDoc: FakeDoc; beforeEach(waitForAsync(() => { - fakeDoc = { body: {}, documentElement: {} }; - TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, FormsModule, ReactiveFormsModule, HammerModule, @@ -49,9 +40,6 @@ describe('IgxSlider', () => { SliderTemplateFormComponent, SliderReactiveFormComponent, SliderWithValueAdjustmentComponent - ], - providers: [ - { provide: ɵDIR_DOCUMENT, useFactory: () => fakeDoc } ] }).compileComponents(); })); @@ -1732,14 +1720,6 @@ describe('IgxSlider', () => { }); describe('Slider RTL', () => { - beforeEach(() => { - fakeDoc.documentElement.dir = 'rtl'; - }); - - afterEach(() => { - fakeDoc.documentElement.dir = 'ltr'; - }); - it('should reflect on the right instead of the left css property of the slider handlers', () => { const fix = TestBed.createComponent(SliderRtlComponent); fix.detectChanges(); @@ -1748,8 +1728,6 @@ describe('IgxSlider', () => { const thumbs = fix.debugElement.queryAll(By.css(THUMB_TAG)); const labels = fix.debugElement.queryAll(By.css(THUMB_LABEL)); - expect(inst.dir.rtl).toEqual(true); - expect(thumbs[0].nativeElement.style['right']).toEqual(`${fix.componentInstance.value.lower}%`); expect(thumbs[1].nativeElement.style['right']).toEqual(`${fix.componentInstance.value.upper}%`); @@ -2061,13 +2039,11 @@ describe('IgxSlider', () => { @Component({ selector: 'igx-slider-rtl', template: ` - +
`, imports: [IgxSliderComponent] }) export class SliderRtlComponent { - public dir = inject(ɵIgxDirectionality); - @ViewChild(IgxSliderComponent) public slider: IgxSliderComponent; diff --git a/projects/igniteui-angular/slider/src/slider/slider.component.ts b/projects/igniteui-angular/slider/src/slider/slider.component.ts index 9c742100f4a..2bd31d7dc65 100644 --- a/projects/igniteui-angular/slider/src/slider/slider.component.ts +++ b/projects/igniteui-angular/slider/src/slider/slider.component.ts @@ -2,7 +2,7 @@ import { AfterContentInit, AfterViewInit, ChangeDetectorRef, Component, ContentC import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { animationFrameScheduler, fromEvent, interval, merge, noop, Observable, Subject, timer } from 'rxjs'; import { takeUntil, throttle, throttleTime } from 'rxjs/operators'; -import { EditorProvider, ɵIgxDirectionality, resizeObservable } from 'igniteui-angular/core'; +import { EditorProvider, isLeftToRight, resizeObservable } from 'igniteui-angular/core'; import { IgxThumbLabelComponent } from './label/thumb-label.component'; import { IgxSliderType, IgxThumbFromTemplateDirective, @@ -47,7 +47,6 @@ export class IgxSliderComponent implements private _el = inject(ElementRef); private _cdr = inject(ChangeDetectorRef); private _ngZone = inject(NgZone); - private _dir = inject(ɵIgxDirectionality); /** * @hidden @@ -1200,19 +1199,13 @@ export class IgxSliderComponent implements return this._el.nativeElement.getBoundingClientRect().width / (this.maxValue - this.minValue) * this.step; } - // private toggleThumb() { - // return this.thumbFrom.isActive ? - // this.thumbTo.nativeElement.focus() : - // this.thumbFrom.nativeElement.focus(); - // } - private valueInRange(value, min = 0, max = 100) { return Math.max(Math.min(value, max), min); } private positionHandler(thumbHandle: ElementRef, labelHandle: ElementRef, position: number) { const percent = `${this.valueToFraction(position) * 100}%`; - const dir = this._dir.rtl ? 'right' : 'left'; + const dir = !isLeftToRight(this._el.nativeElement) ? 'right' : 'left'; if (thumbHandle) { thumbHandle.nativeElement.style[dir] = percent; @@ -1368,7 +1361,8 @@ export class IgxSliderComponent implements trackLeftIndention = Math.round((1 / positionGap * fromPosition) * 100); } - trackLeftIndention = this._dir.rtl ? -trackLeftIndention : trackLeftIndention; + const rtl = !isLeftToRight(this._el.nativeElement); + trackLeftIndention = rtl ? -trackLeftIndention : trackLeftIndention; this.renderer.setStyle(this.trackRef.nativeElement, 'transform', `scaleX(${positionGap}) translateX(${trackLeftIndention}%)`); } else { this.renderer.setStyle(this.trackRef.nativeElement, 'transform', `scaleX(${toPosition})`); diff --git a/projects/igniteui-angular/slider/src/slider/thumb/thumb-slider.component.ts b/projects/igniteui-angular/slider/src/slider/thumb/thumb-slider.component.ts index b744b5eb050..30c3cf9ceca 100644 --- a/projects/igniteui-angular/slider/src/slider/thumb/thumb-slider.component.ts +++ b/projects/igniteui-angular/slider/src/slider/thumb/thumb-slider.component.ts @@ -3,7 +3,7 @@ import { takeUntil } from 'rxjs/operators'; import { SliderHandle } from '../slider.common'; import { Subject } from 'rxjs'; import { NgClass } from '@angular/common'; -import { ɵIgxDirectionality } from 'igniteui-angular/core'; +import { isLeftToRight } from 'igniteui-angular/core'; /** * @hidden @@ -15,7 +15,6 @@ import { ɵIgxDirectionality } from 'igniteui-angular/core'; }) export class IgxSliderThumbComponent implements OnInit, OnDestroy { private _elementRef = inject(ElementRef); - private _dir = inject(ɵIgxDirectionality); @Input() public value: any; @@ -210,11 +209,12 @@ export class IgxSliderThumbComponent implements OnInit, OnDestroy { } let increment = 0; + const isRTL = !isLeftToRight(this._elementRef.nativeElement); const stepWithDir = (rtl: boolean) => rtl ? this.step * -1 : this.step; if (event.key.endsWith('Left')) { - increment = stepWithDir(!this._dir.rtl); + increment = stepWithDir(!isRTL); } else if (event.key.endsWith('Right')) { - increment = stepWithDir(this._dir.rtl); + increment = stepWithDir(isRTL); } else { return; } @@ -278,10 +278,12 @@ export class IgxSliderThumbComponent implements OnInit, OnDestroy { } private calculateTrackUpdate(mouseX: number): number { - const scaleX = this._dir.rtl ? this.thumbPositionX - mouseX : mouseX - this.thumbPositionX; + const scaleX = !isLeftToRight(this._elementRef.nativeElement) + ? this.thumbPositionX - mouseX + : mouseX - this.thumbPositionX; const stepDistanceCenter = this.stepDistance / 2; - // If the thumb scale range (slider update) is less thàn a half step, + // If the thumb scale range (slider update) is less than a half step, // the position stays the same. const scaleXPositive = Math.abs(scaleX); if (scaleXPositive < stepDistanceCenter) { diff --git a/projects/igniteui-angular/stepper/src/stepper/step/step.component.ts b/projects/igniteui-angular/stepper/src/stepper/step/step.component.ts index a2c09f9f43d..afc3884f99f 100644 --- a/projects/igniteui-angular/stepper/src/stepper/step/step.component.ts +++ b/projects/igniteui-angular/stepper/src/stepper/step/step.component.ts @@ -7,7 +7,7 @@ import { NgClass, NgTemplateOutlet } from '@angular/common'; import { IgxRippleDirective } from 'igniteui-angular/directives'; import { ToggleAnimationPlayer, ToggleAnimationSettings } from 'igniteui-angular/expansion-panel'; import { CarouselAnimationDirection, IgxSlideComponentBase } from 'igniteui-angular/carousel'; -import { ɵIgxDirectionality, PlatformUtil } from 'igniteui-angular/core'; +import { isLeftToRight, PlatformUtil } from 'igniteui-angular/core'; let NEXT_ID = 0; @@ -45,7 +45,6 @@ export class IgxStepComponent extends ToggleAnimationPlayer implements IgxStep, protected platform = inject(PlatformUtil); protected stepperService = inject(IgxStepperService); private element = inject>(ElementRef); - private dir = inject(ɵIgxDirectionality); /** @@ -433,6 +432,8 @@ export class IgxStepComponent extends ToggleAnimationPlayer implements IgxStep, /** @hidden @internal */ public handleNavigation(key: string): void { + const rtl = !isLeftToRight(this.nativeElement); + switch (key) { case this.platform.KEYMAP.HOME: this.stepper.steps.filter(s => s.isAccessible)[0]?.nativeElement.focus(); @@ -444,7 +445,7 @@ export class IgxStepComponent extends ToggleAnimationPlayer implements IgxStep, this.previousStep?.nativeElement.focus(); break; case this.platform.KEYMAP.ARROW_LEFT: - if (this.dir.rtl && this.stepper.orientation === IgxStepperOrientation.Horizontal) { + if (rtl && this.stepper.orientation === IgxStepperOrientation.Horizontal) { this.nextStep?.nativeElement.focus(); } else { this.previousStep?.nativeElement.focus(); @@ -454,7 +455,7 @@ export class IgxStepComponent extends ToggleAnimationPlayer implements IgxStep, this.nextStep?.nativeElement.focus(); break; case this.platform.KEYMAP.ARROW_RIGHT: - if (this.dir.rtl && this.stepper.orientation === IgxStepperOrientation.Horizontal) { + if (rtl && this.stepper.orientation === IgxStepperOrientation.Horizontal) { this.previousStep?.nativeElement.focus(); } else { this.nextStep?.nativeElement.focus(); diff --git a/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts b/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts index 4704d3de696..2158a877f9d 100644 --- a/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts +++ b/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts @@ -6,7 +6,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { take } from 'rxjs/operators'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { IgxInputDirective, IgxInputGroupComponent } from '../../../input-group/src/public_api'; -import { IgxAngularAnimationService, PlatformUtil, ɵDirection } from 'igniteui-angular/core'; +import { IgxAngularAnimationService, PlatformUtil } from 'igniteui-angular/core'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxStepComponent } from './step/step.component'; import { @@ -22,7 +22,6 @@ import { import { IgxStepperComponent } from './stepper.component'; import { IgxStepActiveIndicatorDirective, IgxStepCompletedIndicatorDirective, IgxStepContentDirective, IgxStepIndicatorDirective, IgxStepInvalidIndicatorDirective, IgxStepSubtitleDirective, IgxStepTitleDirective } from './stepper.directive'; import { IgxStepperService } from './stepper.service'; -import { IgxDirectionality } from 'igniteui-angular/core/src/services/direction/directionality'; const STEPPER_CLASS = 'igx-stepper'; const STEPPER_HEADER = 'igx-stepper__header'; @@ -977,7 +976,6 @@ describe('Stepper service unit tests', () => { let mockAnimationService: any; let mockPlatform: any; let mockDocument: any; - let mockDir: any; let steps: IgxStepComponent[] = []; let stepper: IgxStepperComponent; @@ -1041,12 +1039,6 @@ describe('Stepper service unit tests', () => { removeEventListener: (_type: string, _listener: (this: HTMLElement, ev: MouseEvent) => any) => { } }; - mockDir = { - value: (): ɵDirection => 'rtl', - document: () => mockDocument, - rtl: () => true - }; - mockCdr = { markForCheck: (): void => { }, detach: (): void => { }, @@ -1064,7 +1056,6 @@ describe('Stepper service unit tests', () => { { provide: IgxAngularAnimationService, useValue: mockAnimationService }, { provide: ElementRef, useValue: mockElementRef }, { provide: IgxStepperService, useValue: stepperService }, - { provide: IgxDirectionality, useValue: mockDir }, { provide: PlatformUtil, useValue: mockPlatform }, IgxStepperComponent, { provide: IGX_STEPPER_COMPONENT, useExisting: IgxStepperComponent }, diff --git a/projects/igniteui-angular/tabs/src/tabs/tabs.directive.ts b/projects/igniteui-angular/tabs/src/tabs/tabs.directive.ts index 3d6e6e322dc..d82c0effde6 100644 --- a/projects/igniteui-angular/tabs/src/tabs/tabs.directive.ts +++ b/projects/igniteui-angular/tabs/src/tabs/tabs.directive.ts @@ -1,10 +1,10 @@ import { - AfterViewInit, ContentChildren, Directive, EventEmitter, + AfterViewInit, ContentChildren, Directive, ElementRef, EventEmitter, Input, OnDestroy, Output, QueryList, booleanAttribute, inject } from '@angular/core'; import { Subscription } from 'rxjs'; -import { IBaseEventArgs, ɵIgxDirectionality } from 'igniteui-angular/core'; +import { IBaseEventArgs, isLeftToRight } from 'igniteui-angular/core'; import { IgxTabItemDirective } from './tab-item.directive'; import { IgxTabContentBase, IgxTabsBase } from './tabs.base'; import { IgxCarouselComponentBase, CarouselAnimationDirection } from 'igniteui-angular/carousel'; @@ -26,8 +26,7 @@ export interface ITabsSelectedItemChangeEventArgs extends ITabsBaseEventArgs { @Directive() export abstract class IgxTabsDirective extends IgxCarouselComponentBase implements IgxTabsBase, AfterViewInit, OnDestroy { - /** @hidden */ - public dir = inject(ɵIgxDirectionality); + protected readonly _element = inject>(ElementRef); /** * Gets/Sets the index of the selected item. @@ -277,14 +276,15 @@ export abstract class IgxTabsDirective extends IgxCarouselComponentBase implemen private triggerPanelAnimations(oldSelectedIndex: number) { const item = this.items.get(this._selectedIndex); + const rtl = !isLeftToRight(this._element.nativeElement); if (item && !this.disableAnimation && this.hasPanels && this.currentItem && !this.currentItem.selected) { - item.direction = (!this.dir.rtl && this._selectedIndex > oldSelectedIndex) || - (this.dir.rtl && this._selectedIndex < oldSelectedIndex) + item.direction = (!rtl && this._selectedIndex > oldSelectedIndex) || + (rtl && this._selectedIndex < oldSelectedIndex) ? CarouselAnimationDirection.NEXT : CarouselAnimationDirection.PREV; if (this.previousItem && this.previousItem.previous) { diff --git a/projects/igniteui-angular/tabs/src/tabs/tabs/tab-header.component.ts b/projects/igniteui-angular/tabs/src/tabs/tabs/tab-header.component.ts index ec8944d7233..b6435106d49 100644 --- a/projects/igniteui-angular/tabs/src/tabs/tabs/tab-header.component.ts +++ b/projects/igniteui-angular/tabs/src/tabs/tabs/tab-header.component.ts @@ -2,7 +2,7 @@ import { AfterViewInit, Component, HostBinding, HostListener, NgZone, OnDestroy, import { IgxTabHeaderDirective } from '../tab-header.directive'; import { IgxTabHeaderBase } from '../tabs.base'; import { IgxTabsComponent } from './tabs.component'; -import { getResizeObserver, ɵIgxDirectionality } from 'igniteui-angular/core'; +import { getResizeObserver, isLeftToRight } from 'igniteui-angular/core'; @Component({ selector: 'igx-tab-header', @@ -13,7 +13,6 @@ import { getResizeObserver, ɵIgxDirectionality } from 'igniteui-angular/core'; export class IgxTabHeaderComponent extends IgxTabHeaderDirective implements AfterViewInit, OnDestroy { protected override tabs = inject(IgxTabsComponent); private ngZone = inject(NgZone); - private dir = inject(ɵIgxDirectionality); /** @hidden @internal */ @HostBinding('class.igx-tabs__header-item--selected') @@ -104,7 +103,9 @@ export class IgxTabHeaderComponent extends IgxTabHeaderDirective implements Afte } private getNewSelectionIndex(newIndex: number, itemsArray: any[], key: string, hasDisabledItems: boolean): number { - if ((key === this.platform.KEYMAP.ARROW_RIGHT && !this.dir.rtl) || (key === this.platform.KEYMAP.ARROW_LEFT && this.dir.rtl)) { + const rtl = !isLeftToRight(this.nativeElement); + + if ((key === this.platform.KEYMAP.ARROW_RIGHT && !rtl) || (key === this.platform.KEYMAP.ARROW_LEFT && rtl)) { newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1; while (hasDisabledItems && itemsArray[newIndex].disabled && newIndex < itemsArray.length) { newIndex = newIndex === itemsArray.length - 1 ? 0 : newIndex + 1; diff --git a/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.ts b/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.ts index edcf617b6e9..7af5f745faf 100644 --- a/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.ts +++ b/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.ts @@ -4,7 +4,7 @@ import { IgxTabsDirective } from '../tabs.directive'; import { NgClass, NgTemplateOutlet } from '@angular/common'; import { IgxIconButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives'; import { IgxIconComponent } from 'igniteui-angular/icon'; -import { getResizeObserver, PlatformUtil } from 'igniteui-angular/core'; +import { getResizeObserver, PlatformUtil, isLeftToRight } from 'igniteui-angular/core'; export const IgxTabsAlignment = { start: 'start', @@ -338,10 +338,11 @@ export class IgxTabsComponent extends IgxTabsDirective implements AfterViewInit, } private getOffset(offset: number): number { - return this.dir.rtl ? -offset : offset; + return isLeftToRight(this._element.nativeElement) ? offset : -offset; } private getElementOffset(element: HTMLElement): number { - return this.dir.rtl ? this.itemsWrapper.nativeElement.offsetWidth - element.offsetLeft - element.offsetWidth : element.offsetLeft; + const rtl = !isLeftToRight(this._element.nativeElement); + return rtl ? this.itemsWrapper.nativeElement.offsetWidth - element.offsetLeft - element.offsetWidth : element.offsetLeft; } }