@progressivewebcomponents/pwa-install

0.2.0 • Public • Published

Published on NPM Published on webcomponents.org

A tiny zero-dependency non-visual native browser web component (custom HTML element and class) that helps implement custom patterns for promoting progressive web apps (PWA) installation.

It's compatible with Google Polymer library data binding.

API

Methods

Method Type Modifiers
prompt (): ?Promise<Object> async
getInstalledRelatedApps (): ?Promise<Array> async

Properties

Property Type Modifiers
isInstallSupported ?boolean readonly
isInstallAvailable ?boolean readonly
platforms ?Array readonly
choiceResult ?Object readonly
isGetInstalledRelatedAppsSupported ?boolean readonly
relatedApps ?Array readonly

Attributes

Attribute Type Modifiers
is-install-supported ?boolean readonly
is-install-available ?boolean readonly
is-get-installed-related-apps-supported ?boolean readonly

Events

Event Bubbles Composed
pwa-install-available true true
pwa-install-installing true true
pwa-install-installed true true
pwa-install-error true true
is-install-supported-changed false false
is-install-available-changed false false
platforms-changed false false
choice-result-changed false false
is-get-installed-related-apps-supported-changed false false
related-apps-changed false false

Install

npm i @progressivewebcomponents/pwa-install

Import

Local

JS

import './node_modules/@progressivewebcomponents/pwa-install/pwa-install.js';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from './node_modules/@progressivewebcomponents/pwa-install/pwa-install-class.js';

HTML

<script
  type="module"
  src="./node_modules/@progressivewebcomponents/pwa-install/pwa-install.js">
</script>
<script type="module">
  import './node_modules/@progressivewebcomponents/pwa-install/pwa-install.js';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from './node_modules/@progressivewebcomponents/pwa-install/pwa-install-class.js';
</script>

Import maps

<script type="importmap">
  {
    "imports": {
      "pwa-install": "./node_modules/@progressivewebcomponents/pwa-install/pwa-install.js",
      "pwa-install/": "./node_modules/@progressivewebcomponents/pwa-install/"
    }
  }
</script>

JS

import 'pwa-install';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from 'pwa-install/pwa-install-class.js';

HTML

<script type="module">
  import 'pwa-install';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from 'pwa-install/pwa-install-class.js';
</script>

Dev Servers / Builders

JS

import '@progressivewebcomponents/pwa-install';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from '@progressivewebcomponents/pwa-install/pwa-install-class.js';

HTML

<script type="module">
  import '@progressivewebcomponents/pwa-install';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from '@progressivewebcomponents/pwa-install/pwa-install-class.js';
</script>

CDN

UNPKG

JS

import 'https://unpkg.com/@progressivewebcomponents/pwa-install';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from 'https://unpkg.com/@progressivewebcomponents/pwa-install/pwa-install-class.js';

HTML

<script
  type="module"
  src="https://unpkg.com/@progressivewebcomponents/pwa-install">
</script>
<script type="module">
  import 'https://unpkg.com/@progressivewebcomponents/pwa-install';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from 'https://unpkg.com/@progressivewebcomponents/pwa-install/pwa-install-class.js';
</script>

ESM CDN

JS

import 'https://esm.sh/@progressivewebcomponents/pwa-install';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from 'https://esm.sh/@progressivewebcomponents/pwa-install/pwa-install-class.js';

HTML

<script
  type="module"
  src="https://esm.sh/@progressivewebcomponents/pwa-install">
</script>
<script type="module">
  import 'https://esm.sh/@progressivewebcomponents/pwa-install';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from 'https://esm.sh/@progressivewebcomponents/pwa-install/pwa-install-class.js';
</script>

Skypack

JS

import 'https://cdn.skypack.dev/@progressivewebcomponents/pwa-install';
Advanced usage

See the Customize section for how to use the code below:

import { PWAInstall } from 'https://cdn.skypack.dev/@progressivewebcomponents/pwa-install/pwa-install-class.js';

HTML

<script
  type="module"
  src="https://cdn.skypack.dev/@progressivewebcomponents/pwa-install">
</script>
<script type="module">
  import 'https://cdn.skypack.dev/@progressivewebcomponents/pwa-install';
</script>
Advanced usage

See the Customize section for how to use the code below:

<script type="module">
  import { PWAInstall } from 'https://cdn.skypack.dev/@progressivewebcomponents/pwa-install/pwa-install-class.js';
</script>

Use

HTML

<pwa-install id="a2hs"></pwa-install>

JS

const pwaInstall = document.getElementById('a2hs');
const choiseResult = await pwaInstall.prompt();

const relatedApps = await pwaInstall.getInstalledRelatedApps();
let isInstallSupportedPropertyValue = pwaInstall.isInstallSupported;

let isInstallAvailablePropertyValue = pwaInstall.isInstallAvailable;

let platformsPropertyValue = pwaInstall.platforms;

let choiceResultPropertyValue = pwaInstall.choiceResult;

let isGetInstalledRelatedAppsSupportedPropertyValue = pwaInstall.isGetInstalledRelatedAppsSupported;

let relatedAppsPropertyValue = pwaInstall.relatedApps;
let isInstallSupportedAttributeValue = pwaInstall.hasAttribute('is-install-supported');

let isInstallAvailableAttributeValue = pwaInstall.hasAttribute('is-install-available');

let isGetInstalledRelatedAppsSupportedAttributeValue = pwaInstall.hasAttribute('is-get-installed-related-apps-supported');
pwaInstall.addEventListener('pwa-install-available', handlePWAInstallAvailableEvent);

pwaInstall.addEventListener('pwa-install-installing', handlePWAInstallInstallingEvent);

pwaInstall.addEventListener('pwa-install-installed', handlePWAInstallInstalledEvent);

pwaInstall.addEventListener('pwa-install-error', handlePWAInstallErrorEvent);
const handlePWAInstallAvailableEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handlePWAInstallInstallingEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handlePWAInstallInstalledEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handlePWAInstallErrorEvent = (event) => {
  // Use event.detail.message.error, event.detail.value and/or run any code
}
Use case

Events can be used to collect telemetry on (promoting) PWA installation and send it to e.g. Google Analytics:

const handlePWAInstallAvailableEvent = (event) => {
  window.gtag?.('event', 'pwa-install', {
    'state': 'available',
    'platforms': event.detail.value,
  });
}

const handlePWAInstallInstallingEvent = (event) => {
  window.gtag?.('event', 'pwa-install', {
    'state': 'installing',
    'outcome': event.detail.value?.outcome,
    'platform': event.detail.value?.platform,
  });
}

const handlePWAInstallInstalledEvent = (event) => {
  window.gtag?.('event', 'pwa-install', {
    'state': 'installed',
    'platform': event.detail.value?.platform,
  });
}

const handlePWAInstallErrorEvent = (event) => {
  window.gtag?.('event', 'pwa-install', {
    'state': 'error',
    'error': event.detail.message.error,
    'platform': event.detail.value?.platform,
  });
}
pwaInstall.addEventListener('is-install-supported-changed', handleIsInstallSupportedPropertyChangedEvent);

pwaInstall.addEventListener('is-install-available-changed', handleIsInstallAvailablePropertyChangedEvent);

pwaInstall.addEventListener('platforms-changed', handlePlatformsPropertyChangedEvent);

pwaInstall.addEventListener('choice-result-changed', handleChoiceResultPropertyChangedEvent);

pwaInstall.addEventListener('is-get-installed-related-apps-supported-changed', handleIsGetInstalledRelatedAppsSupportedPropertyChangedEvent);

pwaInstall.addEventListener('related-apps-changed', handleRelatedAppsPropertyChangedEvent);
const handleIsInstallSupportedPropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handleIsInstallAvailablePropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handlePlatformsPropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handleChoiceResultPropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handleIsGetInstalledRelatedAppsSupportedPropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}

const handleRelatedAppsPropertyChangedEvent = (event) => {
  // Use event.detail.value and/or run any code
}
Use case

Events can be used to update the property values:

const handleIsInstallSupportedPropertyChangedEvent = (event) => {
  isInstallSupportedPropertyValue = event.detail.value;
}

const handleIsInstallAvailablePropertyChangedEvent = (event) => {
  isInstallAvailablePropertyValue = event.detail.value;
}

const handlePlatformsPropertyChangedEvent = (event) => {
  platformsPropertyValue = event.detail.value;
}

const handleChoiceResultPropertyChangedEvent = (event) => {
  choiceResultPropertyValue = event.detail.value;
}

const handleIsGetInstalledRelatedAppsSupportedPropertyChangedEvent = (event) => {
  isGetInstalledRelatedAppsSupportedPropertyValue = event.detail.value;
}

const handleRelatedAppsPropertyChangedEvent = (event) => {
  relatedAppsPropertyValue = event.detail.value;
}

CSS

#a2hs[is-install-supported]

#a2hs[is-install-available]

#a2hs[is-get-installed-related-apps-supported]
Use case

CSS attribute selectors can be used to show/hide and/or style other HTML elements e.g. the UI for promoting PWA installation:

<pwa-install id="a2hs"></pwa-install>

<button
  id="install"
  onclick="document.getElementById('a2hs').prompt()">
    Install
</button>
#install {
  visibility: hidden;
}

:has(#a2hs[is-install-available]) #install {
  visibility: visible;
}

Lit

<pwa-install
  id="a2hs"

  @pwa-install-available="${this.handlePWAInstallAvailableEvent}"
  @pwa-install-installing="${this.handlePWAInstallInstallingEvent}"
  @pwa-install-installed="${this.handlePWAInstallInstalledEvent}"
  @pwa-install-error="${this.handlePWAInstallErrorEvent}"

  @is-install-supported-changed="${this.handleIsInstallSupportedPropertyChangedEvent}"
  @is-install-available-changed="${this.handleIsInstallAvailablePropertyChangedEvent}"
  @platforms-changed="${this.handlePlatformsPropertyChangedEvent}"
  @choice-result-changed="${this.handleChoiceResultPropertyChangedEvent}"
  @is-get-installed-related-apps-supported-changed="${this.handleIsGetInstalledRelatedAppsSupportedPropertyChangedEvent}"
  @related-apps-changed="${this.handleRelatedAppsPropertyChangedEvent}">
</pwa-install>
const pwaInstall = this.shadowRoot.getElementById('a2hs');

Polymer

<pwa-install
  id="a2hs"

  is-install-supported="{{isInstallSupportedPropertyValue}}"
  is-install-available="{{isInstallAvailablePropertyValue}}"
  platforms="{{platformsPropertyValue}}"
  choice-result="{{choiceResultPropertyValue}}"
  is-get-installed-related-apps-supported="{{isGetInstalledRelatedAppsSupportedPropertyValue}}"
  related-apps="{{relatedAppsPropertyValue}}"

  on-pwa-install-available="handlePWAInstallAvailableEvent"
  on-pwa-install-installing="handlePWAInstallInstallingEvent"
  on-pwa-install-installed="handlePWAInstallInstalledEvent"
  on-pwa-install-error="handlePWAInstallErrorEvent"

  on-is-install-supported-changed="handleIsInstallSupportedPropertyChangedEvent"
  on-is-install-available-changed="handleIsInstallAvailablePropertyChangedEvent"
  on-platforms-changed="handlePlatformsPropertyChangedEvent"
  on-choice-result-changed="handleChoiceResultPropertyChangedEvent"
  on-is-get-installed-related-apps-supported-changed="handleIsGetInstalledRelatedAppsSupportedPropertyChangedEvent"
  on-related-apps-changed="handleRelatedAppsPropertyChangedEvent">
</pwa-install>
const pwaInstall = this.$.a2hs;
Use case

Property values can be used to show/hide and/or change the state of other HTML elements e.g. the UI for promoting PWA installation:

<pwa-install
  id="a2hs"
  is-install-supported="{{isInstallSupportedPropertyValue}}"
  is-install-available="{{isInstallAvailablePropertyValue}}">
</pwa-install>

<button
  on-click="handleInstallButtonClick"
  hidden$="[[!isInstallSupportedPropertyValue]]"
  disabled$="[[!isInstallAvailablePropertyValue]]">
    Install
</button>
handleInstallButtonClick() {
  this.$.a2hs.prompt();
}

Customize

PWAInstall class can be imported without registering <pwa-install> custom HTML element. It can be used to register the web component with a different custom HTML element name:

import { PWAInstall } from 'pwa-install/pwa-install-class.js';

customElements.define('your-custom-element-name', PWAInstall);

or customize the web component:

import { PWAInstall } from 'pwa-install/pwa-install-class.js';

class YourCustomElement extends PWAInstall {
  // Add or override methods, properties, attributes, events, etc.
}

customElements.define('your-custom-element-name', YourCustomElement);
<your-custom-element-name id="a2hs"></your-custom-element-name>

Further reading

Patterns for promoting PWA installation

Native app install prompt

Is your app installed? getInstalledRelatedApps() will tell you!

Detect if your native app is installed from your web site

What does it take to be installable?

Add a web app manifest

Dependencies (0)

    Dev Dependencies (0)

      Package Sidebar

      Install

      npm i @progressivewebcomponents/pwa-install

      Weekly Downloads

      317

      Version

      0.2.0

      License

      MIT

      Unpacked Size

      26.4 kB

      Total Files

      4

      Last publish

      Collaborators

      • alexey.rodionov