@postnord/web-components
Version:
PostNord Web Components
752 lines (751 loc) • 28.1 kB
JavaScript
/*!
* 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 {
constructor() {
this.tooltipOpen = false;
this.tooltipUpwards = false;
this.label = '';
this.appearance = '';
this.variant = '';
this.small = false;
this.loading = false;
this.icon = undefined;
this.iconOnly = false;
this.leftIcon = false;
this.tooltip = undefined;
this.tooltipUp = false;
this.type = 'button';
this.form = undefined;
this.href = undefined;
this.rel = undefined;
this.target = undefined;
this.download = undefined;
this.buttonId = null;
this.arialabel = null;
this.arialabelledby = null;
this.ariacurrent = null;
this.ariacontrols = null;
this.ariapressed = null;
this.ariahaspopup = null;
this.ariaexpanded = null;
this.noTab = false;
}
buttonEl;
tooltipEl;
tooltipDx;
openEvents = ['mouseover', 'focus'];
closeEvents = ['mouseleave', 'blur', 'touchcancel', 'touchleave'];
eventListeners = [...this.openEvents, ...this.closeEvents];
hostElement;
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.
**/
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: '180829edde0e9471638f6a432a23470b4a024201' }, h(TagName, { key: 'a379079e76aa1a3fdea4a5c17e0de204fbb546d0', 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: '836e8be4f23275acc3e2918f99529ab198802d1a', class: "pn-button-bg" }), h("div", { key: 'ae1b5955bbff42463cb4076fc069daddff7c45f2', class: "pn-button-content" }, h("div", { key: '32e7974f93b3f674ed587419e2cd15e1a7f163d4', class: "pn-button-text", hidden: this.showIconOnly() }, this.label, h("slot", { key: '67672d69b3b7c4192c3533c3d77701c7e75e390a' })), !!this.icon && h("pn-icon", { key: 'b884299835c2844f5e49bb10273490d058f6098d', icon: this.icon })), h("pn-spinner", { key: '5d514b4e8b1a0f434e8b44e9c3ae50ed9d80971c', light: true }), h("div", { key: '2b1a2cc98d6d9e6732b2f479cbc29f88868f498b', class: "pn-button-tooltip", hidden: !this.tooltip, ref: el => (this.tooltipEl = el) }, h("span", { key: '8dd356c33fced3deddea322b48b8fd74c43b902f', 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": [],
"text": "The label of the button, this is the same as using the default slot."
},
"attribute": "label",
"reflect": false,
"defaultValue": "''"
},
"appearance": {
"type": "string",
"mutable": false,
"complexType": {
"original": "PnButtonAppearance",
"resolved": "\"\" | \"light\" | \"warning\"",
"references": {
"PnButtonAppearance": {
"location": "import",
"path": "@/index",
"id": "src/index.ts::PnButtonAppearance"
}
}
},
"required": false,
"optional": true,
"docs": {
"tags": [{
"name": "category",
"text": "Visual"
}],
"text": "Select the button appearance: default (blue), `light` (white) and `warning` (red)."
},
"attribute": "appearance",
"reflect": false,
"defaultValue": "''"
},
"variant": {
"type": "string",
"mutable": false,
"complexType": {
"original": "PnButtonVariant",
"resolved": "\"\" | \"borderless\" | \"outlined\"",
"references": {
"PnButtonVariant": {
"location": "import",
"path": "@/index",
"id": "src/index.ts::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)."
},
"attribute": "variant",
"reflect": false,
"defaultValue": "''"
},
"small": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [{
"name": "category",
"text": "Visual"
}],
"text": "Use the small button."
},
"attribute": "small",
"reflect": false,
"defaultValue": "false"
},
"loading": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [{
"name": "category",
"text": "Visual"
}],
"text": "Display the loading indicator."
},
"attribute": "loading",
"reflect": true,
"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."
},
"attribute": "icon",
"reflect": false
},
"iconOnly": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"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": "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`."
},
"attribute": "icon-only",
"reflect": false,
"defaultValue": "false"
},
"leftIcon": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"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."
},
"attribute": "left-icon",
"reflect": false,
"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."
},
"attribute": "tooltip",
"reflect": false
},
"tooltipUp": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [{
"name": "category",
"text": "Tooltip"
}],
"text": "Prefer the tooltip to open upwards. Will still go downwards if there is no space."
},
"attribute": "tooltip-up",
"reflect": false,
"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."
},
"attribute": "type",
"reflect": false,
"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."
},
"attribute": "form",
"reflect": false
},
"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)."
},
"attribute": "href",
"reflect": false
},
"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."
},
"attribute": "rel",
"reflect": false
},
"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."
},
"attribute": "target",
"reflect": false
},
"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."
},
"attribute": "download",
"reflect": false
},
"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."
},
"attribute": "button-id",
"reflect": false,
"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."
},
"attribute": "arialabel",
"reflect": false,
"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."
},
"attribute": "arialabelledby",
"reflect": false,
"defaultValue": "null"
},
"ariacurrent": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [{
"name": "category",
"text": "HTML attributes"
}],
"text": "HTML aria-current attribute."
},
"attribute": "ariacurrent",
"reflect": false,
"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."
},
"attribute": "ariacontrols",
"reflect": false,
"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."
},
"attribute": "ariapressed",
"reflect": false,
"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."
},
"attribute": "ariahaspopup",
"reflect": false,
"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."
},
"attribute": "ariaexpanded",
"reflect": false,
"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."
},
"attribute": "no-tab",
"reflect": false,
"defaultValue": "false"
}
};
}
static get states() {
return {
"tooltipOpen": {},
"tooltipUpwards": {}
};
}
static get events() {
return [{
"method": "pnClick",
"name": "pnClick",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"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"
}];
}
}
//# sourceMappingURL=pn-button.js.map