fix(img): draggable attribute is now inherited to inner img element (#24781)

Resolves #21325

Co-authored-by: Celilsemi Sam Erkiner <celilsemi@erkiner.com>
Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
Sean Perkins
2022-02-21 11:50:57 -05:00
committed by GitHub
parent 243f67362f
commit 19ac2389eb
13 changed files with 133 additions and 27 deletions

View File

@ -5,7 +5,7 @@ import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { AnimationBuilder, Color } from '../../interface'; import { AnimationBuilder, Color } from '../../interface';
import { ButtonInterface } from '../../utils/element-interface'; import { ButtonInterface } from '../../utils/element-interface';
import { inheritAttributes } from '../../utils/helpers'; import { Attributes, inheritAttributes } from '../../utils/helpers';
import { createColorClasses, hostContext, openURL } from '../../utils/theme'; import { createColorClasses, hostContext, openURL } from '../../utils/theme';
/** /**
@ -24,7 +24,7 @@ import { createColorClasses, hostContext, openURL } from '../../utils/theme';
shadow: true shadow: true
}) })
export class BackButton implements ComponentInterface, ButtonInterface { export class BackButton implements ComponentInterface, ButtonInterface {
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
@Element() el!: HTMLElement; @Element() el!: HTMLElement;

View File

@ -3,7 +3,7 @@ import { chevronForwardOutline, ellipsisHorizontal } from 'ionicons/icons';
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { AnimationBuilder, BreadcrumbCollapsedClickEventDetail, Color, RouterDirection } from '../../interface'; import { AnimationBuilder, BreadcrumbCollapsedClickEventDetail, Color, RouterDirection } from '../../interface';
import { inheritAttributes } from '../../utils/helpers'; import { Attributes, inheritAttributes } from '../../utils/helpers';
import { createColorClasses, hostContext, openURL } from '../../utils/theme'; import { createColorClasses, hostContext, openURL } from '../../utils/theme';
/** /**
@ -22,7 +22,7 @@ import { createColorClasses, hostContext, openURL } from '../../utils/theme';
shadow: true shadow: true
}) })
export class Breadcrumb implements ComponentInterface { export class Breadcrumb implements ComponentInterface {
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
private collapsedRef?: HTMLElement; private collapsedRef?: HTMLElement;
/** @internal */ /** @internal */

View File

@ -3,7 +3,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { AnimationBuilder, Color, RouterDirection } from '../../interface'; import { AnimationBuilder, Color, RouterDirection } from '../../interface';
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface'; import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
import { hasShadowDom, inheritAttributes } from '../../utils/helpers'; import { Attributes, hasShadowDom, inheritAttributes } from '../../utils/helpers';
import { createColorClasses, hostContext, openURL } from '../../utils/theme'; import { createColorClasses, hostContext, openURL } from '../../utils/theme';
/** /**
@ -28,7 +28,7 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
private inItem = false; private inItem = false;
private inListHeader = false; private inListHeader = false;
private inToolbar = false; private inToolbar = false;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
@Element() el!: HTMLElement; @Element() el!: HTMLElement;

View File

@ -1,7 +1,7 @@
import { Component, ComponentInterface, Element, Host, Prop, h, writeTask } from '@stencil/core'; import { Component, ComponentInterface, Element, Host, Prop, h, writeTask } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { componentOnReady, inheritAttributes } from '../../utils/helpers'; import { Attributes, componentOnReady, inheritAttributes } from '../../utils/helpers';
import { hostContext } from '../../utils/theme'; import { hostContext } from '../../utils/theme';
import { cloneElement, createHeaderIndex, handleContentScroll, handleHeaderFade, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils'; import { cloneElement, createHeaderIndex, handleContentScroll, handleHeaderFade, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils';
@ -21,7 +21,7 @@ export class Header implements ComponentInterface {
private contentScrollCallback?: any; private contentScrollCallback?: any;
private intersectionObserver?: any; private intersectionObserver?: any;
private collapsibleMainHeader?: HTMLElement; private collapsibleMainHeader?: HTMLElement;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
@Element() el!: HTMLElement; @Element() el!: HTMLElement;

View File

@ -1,6 +1,7 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core'; import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { Attributes, inheritAttributes } from '../../utils/helpers';
/** /**
* @part image - The inner `img` element. * @part image - The inner `img` element.
@ -13,6 +14,7 @@ import { getIonMode } from '../../global/ionic-global';
export class Img implements ComponentInterface { export class Img implements ComponentInterface {
private io?: IntersectionObserver; private io?: IntersectionObserver;
private inheritedAttributes: Attributes = {};
@Element() el!: HTMLElement; @Element() el!: HTMLElement;
@ -45,6 +47,10 @@ export class Img implements ComponentInterface {
/** Emitted when the img fails to load */ /** Emitted when the img fails to load */
@Event() ionError!: EventEmitter<void>; @Event() ionError!: EventEmitter<void>;
componentWillLoad() {
this.inheritedAttributes = inheritAttributes(this.el, ['draggable']);
}
componentDidLoad() { componentDidLoad() {
this.addIO(); this.addIO();
} }
@ -100,17 +106,38 @@ export class Img implements ComponentInterface {
} }
render() { render() {
const { loadSrc, alt, onLoad, loadError, inheritedAttributes } = this;
const { draggable } = inheritedAttributes;
return ( return (
<Host class={getIonMode(this)}> <Host class={getIonMode(this)}>
<img <img
decoding="async" decoding="async"
src={this.loadSrc} src={loadSrc}
alt={this.alt} alt={alt}
onLoad={this.onLoad} onLoad={onLoad}
onError={this.loadError} onError={loadError}
part="image" part="image"
draggable={isDraggable(draggable)}
/> />
</Host> </Host>
); );
} }
} }
/**
* Enumerated strings must be set as booleans
* as Stencil will not render 'false' in the DOM.
* The need to explicitly render draggable="true"
* as only certain elements are draggable by default.
* https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable.
*/
const isDraggable = (draggable?: string): boolean | undefined => {
switch (draggable) {
case 'true':
return true;
case 'false':
return false;
default:
return undefined;
}
}

View File

@ -0,0 +1,17 @@
import { newE2EPage } from '@stencil/core/testing';
test('img: draggable', async () => {
const page = await newE2EPage({
url: '/src/components/img/test/draggable?ionic:_testing=true'
});
const imgDraggableTrue = await page.find('#img-draggable-true >>> img');
expect(imgDraggableTrue.getAttribute('draggable')).toEqual('true');
const imgDraggableFalse = await page.find('#img-draggable-false >>> img');
expect(imgDraggableFalse.getAttribute('draggable')).toEqual('false');
const imgDraggableUnset = await page.find('#img-draggable-unset >>> img');
expect(imgDraggableUnset.getAttribute('draggable')).toEqual(null);
});

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<title>Img - Draggable</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
<style>
ion-img::part(image) {
border: 1px solid rgba(0, 0, 0, 0.5);
border-radius: 4px;
height: 100px;
width: 100px;
}
</style>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Img - Draggable</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-list>
<ion-item>
<ion-label>Draggable</ion-label>
<ion-img id="img-draggable-true" draggable="true"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAARQAQMAAAA2ut43AAAABlBMVEXMzMz////TjRV2AAAEPUlEQVR42u3RMREAMBDDsPAn/eXhavOq87Ztu7u7+6eBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBf2hvgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgatgn4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGr7S0wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBwFewzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcLW9BQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq6CfQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgautrfAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAVbDPwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNX2FhgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGLgK9hkYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBi42t4CAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV8E+AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1fbW2BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYOAq2GdgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGDgansLDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMXAX7DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFxtb4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrYJ+BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq+0tMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcBXsMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHC1vQUGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgaugn0GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGjvYD5WuYrpZqdmcAAAAASUVORK5CYII=">
</ion-img>
</ion-item>
<ion-item>
<ion-label>Not draggable (draggable="false")</ion-label>
<ion-img id="img-draggable-false" draggable="false"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAARQAQMAAAA2ut43AAAABlBMVEXMzMz////TjRV2AAAEPUlEQVR42u3RMREAMBDDsPAn/eXhavOq87Ztu7u7+6eBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBf2hvgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgatgn4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGr7S0wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBwFewzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcLW9BQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq6CfQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgautrfAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAVbDPwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNX2FhgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGLgK9hkYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBi42t4CAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV8E+AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1fbW2BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYOAq2GdgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGDgansLDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMXAX7DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFxtb4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrYJ+BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq+0tMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcBXsMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHC1vQUGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgaugn0GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGjvYD5WuYrpZqdmcAAAAASUVORK5CYII=">
</ion-img>
</ion-item>
<ion-item>
<ion-label>Draggable (draggable not set)</ion-label>
<ion-img id="img-draggable-unset"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAARQAQMAAAA2ut43AAAABlBMVEXMzMz////TjRV2AAAEPUlEQVR42u3RMREAMBDDsPAn/eXhavOq87Ztu7u7+6eBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBf2hvgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgatgn4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGr7S0wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBwFewzMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcLW9BQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq6CfQYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgautrfAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAVbDPwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNX2FhgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGLgK9hkYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBi42t4CAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDV8E+AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA1fbW2BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYOAq2GdgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGDgansLDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMXAX7DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDFxtb4GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrYJ+BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBq+0tMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcBXsMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMHC1vQUGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgaugn0GBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGjvYD5WuYrpZqdmcAAAAASUVORK5CYII">
</ion-img>
</ion-item>
</ion-list>
</ion-content>
</ion-app>
</body>
</html>

View File

@ -2,7 +2,7 @@ import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Hos
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { AutocompleteTypes, Color, InputChangeEventDetail, StyleEventDetail, TextFieldTypes } from '../../interface'; import { AutocompleteTypes, Color, InputChangeEventDetail, StyleEventDetail, TextFieldTypes } from '../../interface';
import { debounceEvent, findItemLabel, inheritAttributes } from '../../utils/helpers'; import { Attributes, debounceEvent, findItemLabel, inheritAttributes } from '../../utils/helpers';
import { createColorClasses } from '../../utils/theme'; import { createColorClasses } from '../../utils/theme';
/** /**
@ -21,7 +21,7 @@ export class Input implements ComponentInterface {
private nativeInput?: HTMLInputElement; private nativeInput?: HTMLInputElement;
private inputId = `ion-input-${inputIds++}`; private inputId = `ion-input-${inputIds++}`;
private didBlurAfterEdit = false; private didBlurAfterEdit = false;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
private isComposing = false; private isComposing = false;
/** /**

View File

@ -5,7 +5,7 @@ import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface'; import { Color } from '../../interface';
import { ButtonInterface } from '../../utils/element-interface'; import { ButtonInterface } from '../../utils/element-interface';
import { inheritAttributes } from '../../utils/helpers'; import { Attributes, inheritAttributes } from '../../utils/helpers';
import { menuController } from '../../utils/menu-controller'; import { menuController } from '../../utils/menu-controller';
import { createColorClasses, hostContext } from '../../utils/theme'; import { createColorClasses, hostContext } from '../../utils/theme';
import { updateVisibility } from '../menu-toggle/menu-toggle-util'; import { updateVisibility } from '../menu-toggle/menu-toggle-util';
@ -25,7 +25,7 @@ import { updateVisibility } from '../menu-toggle/menu-toggle-util';
shadow: true shadow: true
}) })
export class MenuButton implements ComponentInterface, ButtonInterface { export class MenuButton implements ComponentInterface, ButtonInterface {
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
@Element() el!: HTMLIonSegmentElement; @Element() el!: HTMLIonSegmentElement;

View File

@ -5,7 +5,7 @@ import { getIonMode } from '../../global/ionic-global';
import { Animation, Gesture, GestureDetail, MenuChangeEventDetail, MenuI, Side } from '../../interface'; import { Animation, Gesture, GestureDetail, MenuChangeEventDetail, MenuI, Side } from '../../interface';
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier'; import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
import { GESTURE_CONTROLLER } from '../../utils/gesture'; import { GESTURE_CONTROLLER } from '../../utils/gesture';
import { assert, clamp, inheritAttributes, isEndSide as isEnd } from '../../utils/helpers'; import { Attributes, assert, clamp, inheritAttributes, isEndSide as isEnd } from '../../utils/helpers';
import { menuController } from '../../utils/menu-controller'; import { menuController } from '../../utils/menu-controller';
import { getOverlay } from '../../utils/overlays'; import { getOverlay } from '../../utils/overlays';
@ -43,7 +43,7 @@ export class Menu implements ComponentInterface, MenuI {
contentEl?: HTMLElement; contentEl?: HTMLElement;
lastFocus?: HTMLElement; lastFocus?: HTMLElement;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
private handleFocus = (ev: FocusEvent) => { private handleFocus = (ev: FocusEvent) => {
/** /**

View File

@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { Color, Gesture, GestureDetail, KnobName, RangeChangeEventDetail, RangeValue, StyleEventDetail } from '../../interface'; import { Color, Gesture, GestureDetail, KnobName, RangeChangeEventDetail, RangeValue, StyleEventDetail } from '../../interface';
import { clamp, debounceEvent, getAriaLabel, inheritAttributes, renderHiddenInput } from '../../utils/helpers'; import { Attributes, clamp, debounceEvent, getAriaLabel, inheritAttributes, renderHiddenInput } from '../../utils/helpers';
import { isRTL } from '../../utils/rtl'; import { isRTL } from '../../utils/rtl';
import { createColorClasses, hostContext } from '../../utils/theme'; import { createColorClasses, hostContext } from '../../utils/theme';
@ -38,7 +38,7 @@ export class Range implements ComponentInterface {
private hasFocus = false; private hasFocus = false;
private rangeSlider?: HTMLElement; private rangeSlider?: HTMLElement;
private gesture?: Gesture; private gesture?: Gesture;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
@Element() el!: HTMLIonRangeElement; @Element() el!: HTMLIonRangeElement;

View File

@ -2,7 +2,7 @@ import { Build, Component, ComponentInterface, Element, Event, EventEmitter, Hos
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { Color, StyleEventDetail, TextareaChangeEventDetail } from '../../interface'; import { Color, StyleEventDetail, TextareaChangeEventDetail } from '../../interface';
import { debounceEvent, findItemLabel, inheritAttributes, raf } from '../../utils/helpers'; import { Attributes, debounceEvent, findItemLabel, inheritAttributes, raf } from '../../utils/helpers';
import { createColorClasses } from '../../utils/theme'; import { createColorClasses } from '../../utils/theme';
/** /**
@ -22,7 +22,7 @@ export class Textarea implements ComponentInterface {
private inputId = `ion-textarea-${textareaIds++}`; private inputId = `ion-textarea-${textareaIds++}`;
private didBlurAfterEdit = false; private didBlurAfterEdit = false;
private textareaWrapper?: HTMLElement; private textareaWrapper?: HTMLElement;
private inheritedAttributes: { [k: string]: any } = {}; private inheritedAttributes: Attributes = {};
/** /**
* This is required for a WebKit bug which requires us to * This is required for a WebKit bug which requires us to

View File

@ -75,6 +75,8 @@ export const componentOnReady = (el: any, callback: any) => {
} }
} }
export type Attributes = { [key: string]: any };
/** /**
* Elements inside of web components sometimes need to inherit global attributes * Elements inside of web components sometimes need to inherit global attributes
* set on the host. For example, the inner input in `ion-input` should inherit * set on the host. For example, the inner input in `ion-input` should inherit
@ -86,7 +88,7 @@ export const componentOnReady = (el: any, callback: any) => {
* does not trigger a re-render. * does not trigger a re-render.
*/ */
export const inheritAttributes = (el: HTMLElement, attributes: string[] = []) => { export const inheritAttributes = (el: HTMLElement, attributes: string[] = []) => {
const attributeObject: { [k: string]: any } = {}; const attributeObject: Attributes = {};
attributes.forEach(attr => { attributes.forEach(attr => {
if (el.hasAttribute(attr)) { if (el.hasAttribute(attr)) {
@ -233,8 +235,8 @@ export const getAriaLabel = (componentEl: HTMLElement, inputId: string): { label
labelText = label.textContent; labelText = label.textContent;
label.setAttribute('aria-hidden', 'true'); label.setAttribute('aria-hidden', 'true');
// if there is no label, check to see if the user has provided // if there is no label, check to see if the user has provided
// one by setting an id on the component and using the label element // one by setting an id on the component and using the label element
} else if (componentId.trim() !== '') { } else if (componentId.trim() !== '') {
label = document.querySelector(`label[for="${componentId}"]`); label = document.querySelector(`label[for="${componentId}"]`);
@ -356,7 +358,7 @@ export const debounce = (func: (...args: any[]) => void, wait = 0) => {
* *
* @returns whether the keys are the same and the values are shallow equal. * @returns whether the keys are the same and the values are shallow equal.
*/ */
export const shallowEqualStringMap = (map1: {[k: string]: any} | undefined, map2: {[k: string]: any} | undefined): boolean => { export const shallowEqualStringMap = (map1: { [k: string]: any } | undefined, map2: { [k: string]: any } | undefined): boolean => {
map1 ??= {}; map1 ??= {};
map2 ??= {}; map2 ??= {};
@ -380,4 +382,4 @@ export const shallowEqualStringMap = (map1: {[k: string]: any} | undefined, map2
} }
return true; return true;
} }