diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 515a96d1f1..b65b235063 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2151,6 +2151,54 @@ declare global { } +declare global { + + namespace StencilComponents { + interface IonImg { + /** + * This attribute defines the alternative text describing the image. Users will see this text displayed if the image URL is wrong, the image is not in one of the supported formats, or if the image is not yet downloaded. + */ + 'alt': string; + /** + * The image URL. This attribute is mandatory for the element. + */ + 'src': string; + } + } + + interface HTMLIonImgElement extends StencilComponents.IonImg, HTMLStencilElement {} + + var HTMLIonImgElement: { + prototype: HTMLIonImgElement; + new (): HTMLIonImgElement; + }; + interface HTMLElementTagNameMap { + 'ion-img': HTMLIonImgElement; + } + interface ElementTagNameMap { + 'ion-img': HTMLIonImgElement; + } + namespace JSX { + interface IntrinsicElements { + 'ion-img': JSXElements.IonImgAttributes; + } + } + namespace JSXElements { + export interface IonImgAttributes extends HTMLAttributes { + /** + * This attribute defines the alternative text describing the image. Users will see this text displayed if the image URL is wrong, the image is not in one of the supported formats, or if the image is not yet downloaded. + */ + 'alt'?: string; + 'onIonImgDidLoad'?: (event: CustomEvent) => void; + /** + * The image URL. This attribute is mandatory for the element. + */ + 'src'?: string; + } + } +} + + declare global { namespace StencilComponents { diff --git a/core/src/components/img/img.scss b/core/src/components/img/img.scss new file mode 100644 index 0000000000..7e0e9aed33 --- /dev/null +++ b/core/src/components/img/img.scss @@ -0,0 +1,12 @@ + +ion-img { + display: block; +} + +ion-img > img { + width: 100%; + height: 100%; + + object-fit: inherit; + object-position: inherit; +} diff --git a/core/src/components/img/img.tsx b/core/src/components/img/img.tsx new file mode 100644 index 0000000000..95a6aaf389 --- /dev/null +++ b/core/src/components/img/img.tsx @@ -0,0 +1,77 @@ +import { Component, Element, Event, EventEmitter, Prop, State, Watch } from '@stencil/core'; + + +@Component({ + tag: 'ion-img', + styleUrl: 'img.scss' +}) +export class Img { + + private io?: IntersectionObserver; + + @Element() el!: HTMLElement; + + @State() loadSrc?: string; + + /** + * This attribute defines the alternative text describing the image. + * Users will see this text displayed if the image URL is wrong, + * the image is not in one of the supported formats, or if the image is not yet downloaded. + */ + @Prop() alt?: string; + + /** + * The image URL. This attribute is mandatory for the element. + */ + @Prop() src?: string; + @Watch('src') + srcChanged() { + this.addIO(); + } + + @Event() ionImgDidLoad!: EventEmitter; + + componentDidLoad() { + this.addIO(); + } + + private addIO() { + if (!this.src) { + return; + } + if ('IntersectionObserver' in window) { + this.removeIO(); + this.io = new IntersectionObserver((data) => { + // because there will only ever be one instance + // of the element we are observing + // we can just use data[0] + if (data[0].isIntersecting) { + this.loadSrc = this.src; + this.removeIO(); + this.ionImgDidLoad.emit(); + } + }); + + this.io.observe(this.el); + } else { + // fall back to setTimeout for Safari and IE + setTimeout(() => this.loadSrc = this.src, 200); + } + } + + private removeIO() { + if (this.io) { + this.io.disconnect(); + this.io = undefined; + } + } + + render() { + return ( + {this.alt} + ); + } +} diff --git a/core/src/components/img/readme.md b/core/src/components/img/readme.md new file mode 100644 index 0000000000..e145b21d2d --- /dev/null +++ b/core/src/components/img/readme.md @@ -0,0 +1,145 @@ +# ion-fab + +Fabs are container elements that contain one or more fab buttons. They should be placed in a fixed position that does not scroll with the content. The following attributes can be used to position the fab with respect to the content: + +| Value | Alignment | Details | +|--------------|------------|---------------------------------------------------------------------------| +| `top` | vertical | Places the container at the top of the content. | +| `bottom` | vertical | Places the container at the bottom of the content. | +| `middle` | vertical | Places the container in the middle vertically. | +| `edge` | vertical | Used to place the container between the content and the header/footer. | +| `left` | horizontal | Places the container on the left. | +| `right` | horizontal | Places the container on the right. | +| `center` | horizontal | Places the container in the center horizontally. | + +The fab should have one main fab button. Fabs can also contain fab lists which contain related buttons that show when the main fab button is clicked. The same fab container can contain several [fab list](../../fab-list/FabList) elements with different side values. + +```html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + + + + + +## Properties + +#### alt + +string + +This attribute defines the alternative text describing the image. +Users will see this text displayed if the image URL is wrong, +the image is not in one of the supported formats, or if the image is not yet downloaded. + + +#### src + +string + +The image URL. This attribute is mandatory for the element. + + +## Attributes + +#### alt + +string + +This attribute defines the alternative text describing the image. +Users will see this text displayed if the image URL is wrong, +the image is not in one of the supported formats, or if the image is not yet downloaded. + + +#### src + +string + +The image URL. This attribute is mandatory for the element. + + +## Events + +#### ionImgDidLoad + + + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/core/src/components/img/test/basic/e2e.js b/core/src/components/img/test/basic/e2e.js new file mode 100644 index 0000000000..82d981a7f1 --- /dev/null +++ b/core/src/components/img/test/basic/e2e.js @@ -0,0 +1,19 @@ +'use strict'; + +const { By, until } = require('selenium-webdriver'); +const { register, Page, platforms } = require('../../../../../scripts/e2e'); + +class E2ETestPage extends Page { + constructor(driver, platform) { + super(driver, `http://localhost:3333/src/components/fab/test/basic?ionic:mode=${platform}`); + } +} + +platforms.forEach(platform => { + describe('fab/basic', () => { + register('should init', driver => { + const page = new E2ETestPage(driver, platform); + return page.navigate('#content'); + }); + }); +}); diff --git a/core/src/components/img/test/basic/index.html b/core/src/components/img/test/basic/index.html new file mode 100644 index 0000000000..f8d9c11fc5 --- /dev/null +++ b/core/src/components/img/test/basic/index.html @@ -0,0 +1,62 @@ + + + + + Floating Action Button - Basic + + + + + + + + + Img - Basic + + + + + + + + + + + + + + + + + + + + Footer + + + + + + + +