more resilient directionality checks; fixes #2188

rtl-for-older-browsers
Cory LaViska 2024-09-26 14:38:30 -04:00
rodzic 761e06220a
commit e91dc034d0
13 zmienionych plików z 38 dodań i 26 usunięć

Wyświetl plik

@ -15,6 +15,7 @@ New versions of Shoelace are released as-needed and generally occur when a criti
## Next
- Fixed a bug in `<sl-relative-time>` where the title attribute would show with redundant info [#2184]
- Updated all checks for directionality to use `this.localize.dir()` instead of `el.matches(:dir(rtl))` so older browsers don't error out [#2188]
## 2.17.1

Wyświetl plik

@ -153,7 +153,7 @@ export default class SlCarousel extends ShoelaceElement {
private handleKeyDown(event: KeyboardEvent) {
if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) {
const target = event.target as HTMLElement;
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const isFocusInPagination = target.closest('[part~="pagination-item"]') !== null;
const isNext =
event.key === 'ArrowDown' || (!isRtl && event.key === 'ArrowRight') || (isRtl && event.key === 'ArrowLeft');
@ -461,7 +461,7 @@ export default class SlCarousel extends ShoelaceElement {
: clamp(index, 0, slides.length - slidesPerPage);
this.activeSlide = newActiveSlide;
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
// Get the index of the next slide. For looping carousel it adds `slidesPerPage`
// to normalize the starting index in order to ignore the first nth clones.

Wyświetl plik

@ -187,7 +187,7 @@ export default class SlDetails extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
return html`
<details

Wyświetl plik

@ -2,6 +2,7 @@ import { clamp } from '../../internal/math.js';
import { classMap } from 'lit/directives/class-map.js';
import { drag } from '../../internal/drag.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property, query } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { watch } from '../../internal/watch.js';
@ -38,6 +39,8 @@ export default class SlImageComparer extends ShoelaceElement {
static styles: CSSResultGroup = [componentStyles, styles];
static scopedElement = { 'sl-icon': SlIcon };
private readonly localize = new LocalizeController(this);
@query('.image-comparer') base: HTMLElement;
@query('.image-comparer__handle') handle: HTMLElement;
@ -46,7 +49,7 @@ export default class SlImageComparer extends ShoelaceElement {
private handleDrag(event: PointerEvent) {
const { width } = this.base.getBoundingClientRect();
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
event.preventDefault();
@ -60,8 +63,8 @@ export default class SlImageComparer extends ShoelaceElement {
}
private handleKeyDown(event: KeyboardEvent) {
const isLtr = this.matches(':dir(ltr)');
const isRtl = this.matches(':dir(rtl)');
const isLtr = this.localize.dir() === 'ltr';
const isRtl = this.localize.dir() === 'rtl';
if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
const incr = event.shiftKey ? 10 : 1;
@ -93,7 +96,7 @@ export default class SlImageComparer extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
return html`
<div

Wyświetl plik

@ -1,6 +1,7 @@
import { classMap } from 'lit/directives/class-map.js';
import { getTextContent, HasSlotController } from '../../internal/slot.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property, query } from 'lit/decorators.js';
import { SubmenuController } from './submenu-controller.js';
import { watch } from '../../internal/watch.js';
@ -47,6 +48,7 @@ export default class SlMenuItem extends ShoelaceElement {
};
private cachedTextLabel: string;
private readonly localize = new LocalizeController(this);
@query('slot:not([name])') defaultSlot: HTMLSlotElement;
@query('.menu-item') menuItem: HTMLElement;
@ -153,7 +155,7 @@ export default class SlMenuItem extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const isSubmenuExpanded = this.submenuController.isExpanded();
return html`

Wyświetl plik

@ -195,7 +195,7 @@ export class SubmenuController implements ReactiveController {
private handlePopupReposition = () => {
const submenuSlot: HTMLSlotElement | null = this.host.renderRoot.querySelector("slot[name='submenu']");
const menu = submenuSlot?.assignedElements({ flatten: true }).filter(el => el.localName === 'sl-menu')[0];
const isRtl = this.host.matches(':dir(rtl)');
const isRtl = getComputedStyle(this.host).direction === 'rtl';
if (!menu) {
return;
}
@ -259,7 +259,7 @@ export class SubmenuController implements ReactiveController {
}
renderSubmenu() {
const isRtl = this.host.matches(':dir(rtl)');
const isRtl = getComputedStyle(this.host).direction === 'rtl';
// Always render the slot, but conditionally render the outer <sl-popup>
if (!this.isConnected) {

Wyświetl plik

@ -1,6 +1,7 @@
import { arrow, autoUpdate, computePosition, flip, offset, platform, shift, size } from '@floating-ui/dom';
import { classMap } from 'lit/directives/class-map.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { offsetParent } from 'composed-offset-position';
import { property, query } from 'lit/decorators.js';
import componentStyles from '../../styles/component.styles.js';
@ -56,6 +57,7 @@ export default class SlPopup extends ShoelaceElement {
private anchorEl: Element | VirtualElement | null;
private cleanup: ReturnType<typeof autoUpdate> | undefined;
private readonly localize = new LocalizeController(this);
/** A reference to the internal popup container. Useful for animating and styling the popup with JavaScript. */
@query('.popup') popup: HTMLElement;
@ -413,7 +415,7 @@ export default class SlPopup extends ShoelaceElement {
//
// Source: https://github.com/floating-ui/floating-ui/blob/cb3b6ab07f95275730d3e6e46c702f8d4908b55c/packages/dom/src/utils/getDocumentRect.ts#L31
//
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const staticSide = { top: 'bottom', right: 'left', bottom: 'top', left: 'right' }[placement.split('-')[0]]!;
this.setAttribute('data-current-placement', placement);

Wyświetl plik

@ -175,7 +175,7 @@ export default class SlRange extends ShoelaceElement implements ShoelaceFormCont
const inputWidth = this.input.offsetWidth;
const tooltipWidth = this.output.offsetWidth;
const thumbSize = getComputedStyle(this.input).getPropertyValue('--thumb-size');
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const percentAsWidth = inputWidth * percent;
// The calculations are used to "guess" where the thumb is located. Since we're using the native range control

Wyświetl plik

@ -2,6 +2,7 @@ import { clamp } from '../../internal/math.js';
import { classMap } from 'lit/directives/class-map.js';
import { eventOptions, property, query, state } from 'lit/decorators.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { styleMap } from 'lit/directives/style-map.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { watch } from '../../internal/watch.js';
@ -35,6 +36,8 @@ export default class SlRating extends ShoelaceElement {
static styles: CSSResultGroup = [componentStyles, styles];
static dependencies = { 'sl-icon': SlIcon };
private readonly localize = new LocalizeController(this);
@query('.rating') rating: HTMLElement;
@state() private hoverValue = 0;
@ -77,7 +80,7 @@ export default class SlRating extends ShoelaceElement {
}
private getValueFromXCoordinate(coordinate: number) {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const { left, right, width } = this.rating.getBoundingClientRect();
const value = isRtl
? this.roundToPrecision(((right - coordinate) / width) * this.max, this.precision)
@ -105,8 +108,8 @@ export default class SlRating extends ShoelaceElement {
}
private handleKeyDown(event: KeyboardEvent) {
const isLtr = this.matches(':dir(ltr)');
const isRtl = this.matches(':dir(rtl)');
const isLtr = this.localize.dir() === 'ltr';
const isRtl = this.localize.dir() === 'rtl';
const oldValue = this.value;
if (this.disabled || this.readonly) {
@ -211,7 +214,7 @@ export default class SlRating extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const counter = Array.from(Array(this.max).keys());
let displayValue = 0;

Wyświetl plik

@ -102,7 +102,7 @@ export default class SlSplitPanel extends ShoelaceElement {
}
private handleDrag(event: PointerEvent) {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
if (this.disabled) {
return;
@ -223,7 +223,7 @@ export default class SlSplitPanel extends ShoelaceElement {
render() {
const gridTemplate = this.vertical ? 'gridTemplateRows' : 'gridTemplateColumns';
const gridTemplateAlt = this.vertical ? 'gridTemplateColumns' : 'gridTemplateRows';
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const primary = `
clamp(
0%,

Wyświetl plik

@ -46,14 +46,13 @@ export default class SlTabGroup extends ShoelaceElement {
static styles: CSSResultGroup = [componentStyles, styles];
static dependencies = { 'sl-icon-button': SlIconButton, 'sl-resize-observer': SlResizeObserver };
private readonly localize = new LocalizeController(this);
private activeTab?: SlTab;
private mutationObserver: MutationObserver;
private resizeObserver: ResizeObserver;
private tabs: SlTab[] = [];
private focusableTabs: SlTab[] = [];
private panels: SlTabPanel[] = [];
private readonly localize = new LocalizeController(this);
@query('.tab-group') tabGroup: HTMLElement;
@query('.tab-group__body') body: HTMLSlotElement;
@ -182,7 +181,7 @@ export default class SlTabGroup extends ShoelaceElement {
// Move focus left or right
if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) {
const activeEl = this.tabs.find(t => t.matches(':focus'));
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
let nextTab: null | SlTab = null;
if (activeEl?.tagName.toLowerCase() === 'sl-tab') {
@ -302,7 +301,7 @@ export default class SlTabGroup extends ShoelaceElement {
const width = currentTab.clientWidth;
const height = currentTab.clientHeight;
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
// We can't used offsetLeft/offsetTop here due to a shadow parent issue where neither can getBoundingClientRect
// because it provides invalid values for animating elements: https://bugs.chromium.org/p/chromium/issues/detail?id=920069
@ -434,7 +433,7 @@ export default class SlTabGroup extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
return html`
<div

Wyświetl plik

@ -223,7 +223,7 @@ export default class SlTreeItem extends ShoelaceElement {
}
render() {
const isRtl = this.matches(':dir(rtl)');
const isRtl = this.localize.dir() === 'rtl';
const showExpandButton = !this.loading && (!this.isLeaf || this.lazy);
return html`

Wyświetl plik

@ -1,5 +1,6 @@
import { clamp } from '../../internal/math.js';
import { html } from 'lit';
import { LocalizeController } from '../../utilities/localize.js';
import { property, query } from 'lit/decorators.js';
import { watch } from '../../internal/watch.js';
import componentStyles from '../../styles/component.styles.js';
@ -89,6 +90,7 @@ export default class SlTree extends ShoelaceElement {
private lastFocusedItem: SlTreeItem | null;
private mutationObserver: MutationObserver;
private clickTarget: SlTreeItem | null = null;
private readonly localize = new LocalizeController(this);
constructor() {
super();
@ -222,8 +224,8 @@ export default class SlTree extends ShoelaceElement {
}
const items = this.getFocusableItems();
const isLtr = this.matches(':dir(ltr)');
const isRtl = this.matches(':dir(rtl)');
const isLtr = this.localize.dir() === 'ltr';
const isRtl = this.localize.dir() === 'rtl';
if (items.length > 0) {
event.preventDefault();