UNPKG

@postnord/web-components

Version:
878 lines (877 loc) 32.7 kB
/*! * Built with Stencil * By PostNord. */ import { Host, h } from "@stencil/core"; import { ripple } from "../../../index"; /** * The `pn-button` is built with a native `button` or `a` element, if you use the `href` attribute. * * @nativeClick Use the `click` event to listen when the button is clicked. */ export class PnButton { buttonEl; tooltipEl; tooltipDx; openEvents = ['mouseover', 'focus']; closeEvents = ['mouseleave', 'blur', 'touchcancel', 'touchleave']; eventListeners = [...this.openEvents, ...this.closeEvents]; hostElement; tooltipOpen = false; tooltipUpwards = false; /** The label of the button, this is the same as using the default slot. @since v7.4.0 */ label = ''; /** * Select the button appearance: default (blue), `light` (white) and `warning` (red). * * @category Visual */ appearance = ''; /** * Select the button variant: default (colored background), `outlined` (bordered, no background) and `borderless` (borderless, no background). * * @category Visual */ variant = ''; /** Use the small button. @category Visual */ small = false; /** Display the loading indicator. @category Visual */ loading = false; /** * The SVG content of the icon you want. * @see {@link https://portal.postnord.com/web-components/?path=/docs/docs-assets--docs pn-design-assets} * @category Icon */ icon; /** * Turn the button into an icon only. Requires `icon` and one of the following props to work: `tooltip`, `arialabel` or `arialabelledby`. * @summary __You need an `icon` selected, as well as either `tooltip`, `arialabel` or `arialabelledby` for this to work__. * @see {@link icon} * @since v7.4.0 * @category Icon */ iconOnly = false; /** * Place the `icon` to the left of the button. * * @summary __You need an `icon` selected for this to work__. * @see {@link icon} * @category Icon */ leftIcon = false; /** * When the user focus/hover the button, the `tooltip` text will show up. * * @category Tooltip */ tooltip; /** * Prefer the tooltip to open upwards. Will still go downwards if there is no space. * @since v7.4.0 * @category Tooltip */ tooltipUp = false; /** Select HTML button type. @category Button */ type = 'button'; /** * Connect this button to a HTML form. * @category Button * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#form HTML button form} */ form; /** Pass an href to make the button into link (a-tag). @category Link */ href; /** The rel attribute of the link. @category Link */ rel; /** The target attribute of the link. @category Link */ target; /** The download attribute of the link. @category Link */ download; /** HTML ID. @category HTML attributes */ buttonId = null; /** HTML aria-label attribute. @category HTML attributes */ arialabel = null; /** HTML aria-labelledby attribute. @category HTML attributes */ arialabelledby = null; /** HTML aria-current attribute. @since v7.9.0 @category HTML attributes */ ariacurrent = null; /** HTML aria-controls attribute. @category HTML attributes */ ariacontrols = null; /** HTML aria-pressed attribute. @category HTML attributes */ ariapressed = null; /** HTML aria-haspopup attribute. @category HTML attributes */ ariahaspopup = null; /** HTML aria-expanded attribute. @category HTML attributes */ ariaexpanded = null; /** HTML tabindex. @category HTML attributes */ noTab = false; openHandler() { if (this.tooltipOpen) this.checkTooltipPosition(); } iconOnlyHandler() { this.checkTooltipPosition(); if (this.tooltip) this.initTooltip(); else this.removeTooltip(); } /** * This event is fired when the `button`/`a` element of the `pn-button` is clicked. * Setting an eventListener for `click` on the `pn-button` will trigger if you click outside of the button area * or if the button is `disabled` with the `loading` prop. * @since v7.4.0 **/ pnClick; componentWillLoad() { this.tooltipUpwards = this.tooltipUp; } componentDidLoad() { this.iconOnlyHandler(); } getRect(element) { return element.getBoundingClientRect(); } initTooltip() { this.eventListeners.forEach(e => this.buttonEl.addEventListener(e, this.toggleTooltip)); } removeTooltip() { this.eventListeners.forEach(e => this.buttonEl.removeEventListener(e, this.toggleTooltip)); } toggleTooltip = (event) => { this.tooltipOpen = this.openEvents.includes(event.type); }; setTooltipOffset() { this.tooltipEl.style.setProperty('--pn-dx', `${this.tooltipDx}px`); } checkTooltipPosition() { this.tooltipEl.style.transform = 'translateX(-50%)'; this.tooltipUpwards = this.tooltipUp; requestAnimationFrame(() => { const { top, x, y, right, height } = this.getRect(this.tooltipEl); const extraMargin = 16; this.tooltipDx = 0; this.tooltipUpwards = this.tooltipUp ? top > height : y + height > window.innerHeight; this.tooltipEl.style.transform = ''; if (x < 0) this.tooltipDx = x * -1 + extraMargin; if (right > window.innerWidth) this.tooltipDx = window.innerWidth - right - extraMargin - 8; requestAnimationFrame(() => this.setTooltipOffset()); }); } getAttributes() { const attrs = this.href ? { 'href': this.href, 'rel': !this.rel && this.target === '_blank' ? 'noopener' : this.rel, 'target': this.target ?? null, 'download': this.download ?? null, 'aria-current': this.ariacurrent, 'aria-disabled': this.loading ? 'true' : null, } : { 'type': this.type, 'form': this.form, 'disabled': this.loading, 'aria-pressed': this.ariapressed, 'aria-controls': this.ariacontrols, 'aria-haspopup': this.ariahaspopup, 'aria-expanded': this.ariaexpanded, }; const appearances = ['light', 'warning']; const variations = ['borderless', 'outlined']; return { 'tabindex': this.noTab || (this.href && this.loading) ? '-1' : null, 'data-small': this.small, 'data-loading': this.loading, 'data-tooltip-open': this.tooltipOpen, 'data-tooltip-upwards': this.tooltipUpwards, 'data-icon-only': this.showIconOnly(), 'data-left-icon': this.leftIcon, 'data-appearance': appearances.includes(this.appearance) ? this.appearance : null, 'data-variant': variations.includes(this.variant) ? this.variant : null, ...attrs, }; } getTagName() { return this.href ? 'a' : 'button'; } showIconOnly() { return !!this.icon && this.iconOnly && !!(this.tooltip || this.arialabel || this.arialabelledby); } handleClick(event) { ripple(event, this.hostElement, '.pn-button-bg'); this.pnClick.emit(event); } render() { const TagName = this.getTagName(); return (h(Host, { key: '9fd62df52e09b5f7915c1652c3bd23c47c40db42' }, h(TagName, { key: 'aecef05e4c20bb9c501399f18b7290a33e5d82e7', class: "pn-button", id: this.buttonId, "aria-label": this.arialabel, "aria-labelledby": this.arialabelledby, onClick: e => this.handleClick(e), ...this.getAttributes(), ref: (el) => (this.buttonEl = el) }, h("div", { key: '9cb56181926a77cd985be9447dd5277720370bf6', class: "pn-button-bg" }), h("div", { key: 'f81963c493162009d2219d72171f753c3ba5dcb8', class: "pn-button-content" }, h("div", { key: 'd6cc476c9bb3eaa59ae9cf80700b33e4bc836494', class: "pn-button-text", hidden: this.showIconOnly() }, this.label, h("slot", { key: '83b07110e17088f980e4a7f0094f5330f7dcc17b' })), !!this.icon && h("pn-icon", { key: '6d352caac885f7f5cf3819a7b555e278e7761259', icon: this.icon })), h("pn-spinner", { key: '3176c1f592b5e48c14f7baccc9366bf0fc0187dd', light: true }), h("div", { key: 'b97ecf99cdf1c4fa0c8db3b26c2eac33c5c9bba4', class: "pn-button-tooltip", hidden: !this.tooltip, ref: el => (this.tooltipEl = el) }, h("span", { key: '7825cd9635f5897db28ee4b32d2ac56a8c9a9b0d', class: "pn-button-tooltip-text" }, this.tooltip))))); } static get is() { return "pn-button"; } static get originalStyleUrls() { return { "$": ["pn-button.scss"] }; } static get styleUrls() { return { "$": ["pn-button.css"] }; } static get properties() { return { "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.4.0" }], "text": "The label of the button, this is the same as using the default slot." }, "getter": false, "setter": false, "reflect": false, "attribute": "label", "defaultValue": "''" }, "appearance": { "type": "string", "mutable": false, "complexType": { "original": "PnButtonAppearance", "resolved": "\"\" | \"light\" | \"warning\"", "references": { "PnButtonAppearance": { "location": "import", "path": "@/index", "id": "src/index.ts::PnButtonAppearance", "referenceLocation": "PnButtonAppearance" } } }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Visual" }], "text": "Select the button appearance: default (blue), `light` (white) and `warning` (red)." }, "getter": false, "setter": false, "reflect": false, "attribute": "appearance", "defaultValue": "''" }, "variant": { "type": "string", "mutable": false, "complexType": { "original": "PnButtonVariant", "resolved": "\"\" | \"borderless\" | \"outlined\"", "references": { "PnButtonVariant": { "location": "import", "path": "@/index", "id": "src/index.ts::PnButtonVariant", "referenceLocation": "PnButtonVariant" } } }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Visual" }], "text": "Select the button variant: default (colored background), `outlined` (bordered, no background) and `borderless` (borderless, no background)." }, "getter": false, "setter": false, "reflect": false, "attribute": "variant", "defaultValue": "''" }, "small": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Visual" }], "text": "Use the small button." }, "getter": false, "setter": false, "reflect": false, "attribute": "small", "defaultValue": "false" }, "loading": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Visual" }], "text": "Display the loading indicator." }, "getter": false, "setter": false, "reflect": true, "attribute": "loading", "defaultValue": "false" }, "icon": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "see", "text": "{@link https://portal.postnord.com/web-components/?path=/docs/docs-assets--docs pn-design-assets}" }, { "name": "category", "text": "Icon" }], "text": "The SVG content of the icon you want." }, "getter": false, "setter": false, "reflect": false, "attribute": "icon" }, "iconOnly": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "summary", "text": "__You need an `icon` selected, as well as either `tooltip`, `arialabel` or `arialabelledby` for this to work__." }, { "name": "see", "text": "{@link icon }" }, { "name": "since", "text": "v7.4.0" }, { "name": "category", "text": "Icon" }], "text": "Turn the button into an icon only. Requires `icon` and one of the following props to work: `tooltip`, `arialabel` or `arialabelledby`." }, "getter": false, "setter": false, "reflect": false, "attribute": "icon-only", "defaultValue": "false" }, "leftIcon": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "summary", "text": "__You need an `icon` selected for this to work__." }, { "name": "see", "text": "{@link icon }" }, { "name": "category", "text": "Icon" }], "text": "Place the `icon` to the left of the button." }, "getter": false, "setter": false, "reflect": false, "attribute": "left-icon", "defaultValue": "false" }, "tooltip": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Tooltip" }], "text": "When the user focus/hover the button, the `tooltip` text will show up." }, "getter": false, "setter": false, "reflect": false, "attribute": "tooltip" }, "tooltipUp": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.4.0" }, { "name": "category", "text": "Tooltip" }], "text": "Prefer the tooltip to open upwards. Will still go downwards if there is no space." }, "getter": false, "setter": false, "reflect": false, "attribute": "tooltip-up", "defaultValue": "false" }, "type": { "type": "string", "mutable": false, "complexType": { "original": "'button' | 'reset' | 'submit' | ''", "resolved": "\"\" | \"button\" | \"reset\" | \"submit\"", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Button" }], "text": "Select HTML button type." }, "getter": false, "setter": false, "reflect": false, "attribute": "type", "defaultValue": "'button'" }, "form": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Button" }, { "name": "see", "text": "{@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#form HTML button form}" }], "text": "Connect this button to a HTML form." }, "getter": false, "setter": false, "reflect": false, "attribute": "form" }, "href": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Link" }], "text": "Pass an href to make the button into link (a-tag)." }, "getter": false, "setter": false, "reflect": false, "attribute": "href" }, "rel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Link" }], "text": "The rel attribute of the link." }, "getter": false, "setter": false, "reflect": false, "attribute": "rel" }, "target": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Link" }], "text": "The target attribute of the link." }, "getter": false, "setter": false, "reflect": false, "attribute": "target" }, "download": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Link" }], "text": "The download attribute of the link." }, "getter": false, "setter": false, "reflect": false, "attribute": "download" }, "buttonId": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML ID." }, "getter": false, "setter": false, "reflect": false, "attribute": "button-id", "defaultValue": "null" }, "arialabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-label attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "arialabel", "defaultValue": "null" }, "arialabelledby": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-labelledby attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "arialabelledby", "defaultValue": "null" }, "ariacurrent": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.9.0" }, { "name": "category", "text": "HTML attributes" }], "text": "HTML aria-current attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "ariacurrent", "defaultValue": "null" }, "ariacontrols": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-controls attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "ariacontrols", "defaultValue": "null" }, "ariapressed": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-pressed attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "ariapressed", "defaultValue": "null" }, "ariahaspopup": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-haspopup attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "ariahaspopup", "defaultValue": "null" }, "ariaexpanded": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML aria-expanded attribute." }, "getter": false, "setter": false, "reflect": false, "attribute": "ariaexpanded", "defaultValue": "null" }, "noTab": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "HTML attributes" }], "text": "HTML tabindex." }, "getter": false, "setter": false, "reflect": false, "attribute": "no-tab", "defaultValue": "false" } }; } static get states() { return { "tooltipOpen": {}, "tooltipUpwards": {} }; } static get events() { return [{ "method": "pnClick", "name": "pnClick", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "since", "text": "v7.4.0" }], "text": "This event is fired when the `button`/`a` element of the `pn-button` is clicked.\nSetting an eventListener for `click` on the `pn-button` will trigger if you click outside of the button area\nor if the button is `disabled` with the `loading` prop." }, "complexType": { "original": "MouseEvent", "resolved": "MouseEvent", "references": { "MouseEvent": { "location": "global", "id": "global::MouseEvent" } } } }]; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "tooltipOpen", "methodName": "openHandler" }, { "propName": "tooltip", "methodName": "iconOnlyHandler" }]; } }