Skip to content

Commit 3974302

Browse files
authored
feat(esl-utils): RTL type detection removed as it is out of current browser support list (#2913)
All supported browsers now handle `scrollLeft` according to spec. RTE type detection was deprecated, and the normalization method was simplified. Affected components: esl-tabs, esl-scrollbar
1 parent 60695cc commit 3974302

File tree

4 files changed

+19
-60
lines changed

4 files changed

+19
-60
lines changed

src/modules/esl-scrollbar/core/esl-scrollbar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {ESLBaseElement} from '../../esl-base-element/core';
22
import {ExportNs} from '../../esl-utils/environment/export-ns';
33
import {isElement} from '../../esl-utils/dom/api';
44
import {isRelativeNode} from '../../esl-utils/dom/traversing';
5-
import {isRTL, RTLScroll, normalizeScrollLeft} from '../../esl-utils/dom/rtl';
5+
import {isRTL, normalizeScrollLeft} from '../../esl-utils/dom/rtl';
66
import {getTouchPoint, getOffsetPoint} from '../../esl-utils/dom/events';
77
import {bind, ready, attr, boolAttr, listen} from '../../esl-utils/decorators';
88
import {rafDecorator} from '../../esl-utils/async/raf';
@@ -184,7 +184,7 @@ export class ESLScrollbar extends ESLBaseElement {
184184
protected normalizePosition(position: number): number {
185185
const relativePosition = Math.min(1, Math.max(0, position));
186186
if (!isRTL(this.$target) || !this.horizontal) return relativePosition;
187-
return RTLScroll.type === 'negative' ? (relativePosition - 1) : (1 - relativePosition);
187+
return relativePosition - 1;
188188
}
189189

190190
/** Scrolls target element to passed position */

src/modules/esl-tab/core/esl-tabs.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {ExportNs} from '../../esl-utils/environment/export-ns';
22
import {ESLBaseElement} from '../../esl-base-element/core';
33
import {rafDecorator} from '../../esl-utils/async/raf';
44
import {memoize, attr, listen, decorate, ready} from '../../esl-utils/decorators';
5-
import {isRTL, RTLScroll} from '../../esl-utils/dom/rtl';
5+
import {isRTL} from '../../esl-utils/dom/rtl';
66
import {debounce} from '../../esl-utils/async/debounce';
77
import {ESLResizeObserverTarget} from '../../esl-event-listener/core';
88
import {ESLMediaRuleList} from '../../esl-media-query/core/esl-media-rule-list';
@@ -103,7 +103,7 @@ export class ESLTabs extends ESLBaseElement {
103103

104104
const {offsetWidth, scrollWidth, scrollLeft} = $scrollableTarget;
105105
const max = scrollWidth - offsetWidth;
106-
const invert = direction === 'left' || (isRTL(this) && RTLScroll.type !== 'reverse');
106+
const invert = direction === 'left' || isRTL(this);
107107
const offset = invert ? -offsetWidth : offsetWidth;
108108

109109
const left = Math.max(0, Math.min(max, scrollLeft + offset));
@@ -130,35 +130,31 @@ export class ESLTabs extends ESLBaseElement {
130130

131131
/** Get scroll offset position from the selected item rectangle */
132132
protected calcScrollOffset(itemRect: DOMRect, areaRect: DOMRect): number | undefined {
133-
const isReversedRTL = isRTL(this) && RTLScroll.type === 'reverse';
134-
135133
if (this.currentScrollableType === 'center') {
136-
const shift = itemRect.left + itemRect.width / 2 - (areaRect.left + areaRect.width / 2);
137-
return isReversedRTL ? -shift : shift;
134+
return itemRect.left + itemRect.width / 2 - (areaRect.left + areaRect.width / 2);
138135
}
139136

140137
// item is out of area from the right side
141138
// else item out is of area from the left side
142139
if (itemRect.right > areaRect.right) {
143-
return isReversedRTL ? Math.floor(areaRect.right - itemRect.right) : Math.ceil(itemRect.right - areaRect.right);
140+
return Math.ceil(itemRect.right - areaRect.right);
144141
} else if (itemRect.left < areaRect.left) {
145-
return isReversedRTL ? Math.ceil(areaRect.left - itemRect.left) : Math.floor(itemRect.left - areaRect.left);
142+
return Math.floor(itemRect.left - areaRect.left);
146143
}
147144
}
148145

149146
protected updateArrows(): void {
150147
const $scrollableTarget = this.$scrollableTarget;
151148
if (!$scrollableTarget) return;
152149

153-
const swapSides = isRTL(this) && RTLScroll.type === 'default';
154150
const scrollStart = Math.abs($scrollableTarget.scrollLeft) > 1;
155151
const scrollEnd = Math.abs($scrollableTarget.scrollLeft) + $scrollableTarget.clientWidth + 1 < $scrollableTarget.scrollWidth;
156152

157153
const $rightArrow = this.querySelector('[data-tab-direction="right"]');
158154
const $leftArrow = this.querySelector('[data-tab-direction="left"]');
159155

160-
$leftArrow && $leftArrow.toggleAttribute('disabled', !(swapSides ? scrollEnd : scrollStart));
161-
$rightArrow && $rightArrow.toggleAttribute('disabled', !(swapSides ? scrollStart : scrollEnd));
156+
$leftArrow && $leftArrow.toggleAttribute('disabled', !scrollStart);
157+
$rightArrow && $rightArrow.toggleAttribute('disabled', !scrollEnd);
162158
}
163159

164160
protected updateMarkers(): void {

src/modules/esl-utils/dom/rtl.ts

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,25 @@
1-
// TODO: Revisit using https://caniuse.com/mdn-api_element_scrollleft in 5.0.0
2-
/** RTL scroll browser behaviors */
3-
export type ScrollType = 'default' | 'negative' | 'reverse';
1+
const DEFAULT_SCROLL_TYPE = 'negative';
2+
3+
/** @deprecated RTL scroll browser behaviors now always returns `negative` value */
4+
export type ScrollType = typeof DEFAULT_SCROLL_TYPE;
45

56
/** Checks if the element in a RTL direction context */
67
export const isRTL = (el?: HTMLElement | null): boolean => getComputedStyle(el || document.body).direction === 'rtl';
78

8-
/** Creates the dummy test element with a horizontal scroll presented */
9-
const createDummyScroll = (): HTMLElement => {
10-
const el = document.createElement('div');
11-
el.appendChild(document.createTextNode('ESL!'));
12-
el.dir = 'rtl';
13-
Object.assign(el.style, {
14-
position: 'absolute',
15-
top: '-1000px',
16-
width: '4px',
17-
height: '1px',
18-
fontSize: '14px',
19-
overflow: 'scroll'
20-
});
21-
return el;
22-
};
23-
9+
/** @deprecated scroll type is now consistent and always returns a `negative` value */
2410
export const testRTLScrollType = (): ScrollType => {
25-
let scrollType: ScrollType = 'default';
26-
const el = createDummyScroll();
27-
document.body.appendChild(el);
28-
if (el.scrollLeft <= 0) {
29-
el.scrollLeft = 2;
30-
scrollType = el.scrollLeft < 2 ? 'negative' : 'reverse';
31-
}
32-
document.body.removeChild(el);
33-
return scrollType;
11+
return DEFAULT_SCROLL_TYPE;
3412
};
3513

36-
let type: ScrollType | null = null;
37-
14+
/** @deprecated scroll type is now consistent and always returns a `negative` value */
3815
export const RTLScroll = {
3916
/** @returns RTL scroll type (lazy, memoized) */
4017
get type(): ScrollType {
41-
if (typeof type === 'string') return type;
42-
return type = testRTLScrollType();
18+
return DEFAULT_SCROLL_TYPE;
4319
}
4420
};
4521

4622
export const normalizeScrollLeft = (el: HTMLElement, value: number | null = null, isRtl: boolean = isRTL(el)): number => {
4723
value = (value === null) ? el.scrollLeft : value;
48-
switch (isRtl ? RTLScroll.type : '') {
49-
case 'negative':
50-
return el.scrollWidth - el.clientWidth + value;
51-
case 'reverse':
52-
return el.scrollWidth - el.clientWidth - value;
53-
default:
54-
return value;
55-
}
24+
return isRtl ? el.scrollWidth - el.clientWidth + value : value;
5625
};

src/modules/esl-utils/dom/test/rtl.test.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {RTLScroll, isRTL, normalizeScrollLeft} from '../rtl';
1+
import {isRTL, normalizeScrollLeft} from '../rtl';
22

33
describe('RTLUtils', () => {
44
describe('isRtl', () => {
@@ -29,19 +29,13 @@ describe('RTLUtils', () => {
2929
jest.spyOn(el, 'scrollWidth', 'get').mockImplementation(() => 1000);
3030
jest.spyOn(el, 'clientWidth', 'get').mockImplementation(() => 100);
3131
jest.spyOn(el, 'scrollLeft', 'get').mockImplementation(() => 200);
32-
jest.spyOn(RTLScroll, 'type', 'get').mockImplementation(() => 'negative');
3332

3433
expect(normalizeScrollLeft(el)).toBe(200);
3534
expect(normalizeScrollLeft(el, 50)).toBe(50);
3635
expect(normalizeScrollLeft(el, 50, false)).toBe(50);
3736
expect(normalizeScrollLeft(el, null, false)).toBe(200);
3837
expect(normalizeScrollLeft(el, 50, true)).toBe(950);
3938
expect(normalizeScrollLeft(el, null, true)).toBe(1100);
40-
41-
jest.spyOn(RTLScroll, 'type', 'get').mockImplementation(() => 'reverse');
42-
43-
expect(normalizeScrollLeft(el, 50, true)).toBe(850);
44-
expect(normalizeScrollLeft(el, null, true)).toBe(700);
4539
});
4640
});
4741
});

0 commit comments

Comments
 (0)