UNPKG

@postnord/web-components

Version:
173 lines (172 loc) 6.28 kB
/*! * Built with Stencil * By PostNord. */ import { h } from "@stencil/core"; import { alert_exclamation_circle, alert_question_circle } from "pn-design-assets/pn-assets/icons.js"; /** * The `pn-tooltip` can display slotted HTML content or a text `string` with the `tooltip` prop. * * Remember that the component is techincally a `button` element, don't put any HTML content that would be out of place in a regular button * (no headlines, other input elements, etc...). */ export class PnTooltip { content; button; openEvents = ['mouseover', 'focus']; closeEvents = ['mouseleave', 'blur', 'touchcancel', 'touchleave']; eventListeners = [...this.openEvents, ...this.closeEvents]; timeout; hostElement; downwards = false; open = false; deltaX = '0'; /** Apply the warning color and change the icon to `!`. */ warning = false; /** Apply the light color if you use a dark background. */ light = false; /** Overrides the slotted content to create a small tooltip instead. @since v7.3.0 */ tooltip; openHandler() { if (this.open) this.checkPosition(); else this.setTransform(); } componentDidLoad() { this.initTooltip(); } setTransform() { this.content.style.transform = `scale(${Number(this.open)}) translateX(-50%) translateX(${this.deltaX}px)`; } getSymbol() { return this.warning ? alert_exclamation_circle : alert_question_circle; } checkPosition() { this.content.style.transition = 'none'; this.content.style.transform = 'scale(1) translateX(-50%)'; this.downwards = false; requestAnimationFrame(() => { const { x, y, right } = this.content.getBoundingClientRect(); const extraMargin = 8; this.deltaX = '0'; this.downwards = y < 0; this.content.style.transform = ''; if (x < 0) this.deltaX = `${x * -1 + extraMargin}`; // left edge if (right > window.innerWidth) this.deltaX = `${window.innerWidth - right - extraMargin}`; // right edge requestAnimationFrame(() => { this.content.style.transition = ''; this.setTransform(); }); }); } initTooltip() { this.eventListeners.forEach(name => this.button.addEventListener(name, (event) => this.toggleTooltip(event))); } toggleTooltip(event) { const status = this.openEvents.includes(event.type); let time = 500; if (status) time = 0; clearTimeout(this.timeout); this.timeout = setTimeout(() => { this.open = status; }, time); } render() { return (h("button", { key: 'b05404e6f5f07fd347bc701860e5653a9dbce3e8', class: "pn-tooltip", "data-light": this.light, "data-warning": this.warning, "data-downwards": this.downwards, "data-open": this.open, ref: el => (this.button = el) }, h("pn-icon", { key: 'f2842073c6434c74b4edc312fde550f71fb46657', icon: this.getSymbol(), "data-simple": !!this.tooltip }), h("div", { key: 'cd9a95132eb2bcacc999fbb2d3e31d5cdee64fed', class: "pn-tooltip-content", "data-simple": !!this.tooltip, ref: el => (this.content = el) }, this.tooltip, h("div", { key: 'd10296fa39d348a197405296d62c5b11c4ccbd92', hidden: !!this.tooltip }, h("slot", { key: 'a12512c517fd7aca30f5dadf6cd8b6fbd1f5da56' }))))); } static get is() { return "pn-tooltip"; } static get originalStyleUrls() { return { "$": ["pn-tooltip.scss"] }; } static get styleUrls() { return { "$": ["pn-tooltip.css"] }; } static get properties() { return { "warning": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Apply the warning color and change the icon to `!`." }, "getter": false, "setter": false, "reflect": false, "attribute": "warning", "defaultValue": "false" }, "light": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Apply the light color if you use a dark background." }, "getter": false, "setter": false, "reflect": false, "attribute": "light", "defaultValue": "false" }, "tooltip": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.3.0" }], "text": "Overrides the slotted content to create a small tooltip instead." }, "getter": false, "setter": false, "reflect": false, "attribute": "tooltip" } }; } static get states() { return { "downwards": {}, "open": {}, "deltaX": {} }; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "open", "methodName": "openHandler" }]; } }