UNPKG

@alegendstale/holly-components

Version:

Reusable UI components created using lit

145 lines (137 loc) 4.78 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { css, html, LitElement } from "lit"; import { property, query } from "lit/decorators.js"; import { condCustomElement } from "../../decorators/condCustomElement.js"; export const styles = css ` :host { display: block; position: relative; --tooltip-x: 0; --tooltip-y: 0; } /* Manual or Click appear when display is true */ :host(:not([trigger="hover"])[display]) p { display: flex; } /* Hover appears when display is true and user is hovering */ :host([trigger="hover"][display]:hover) p { display: flex; } /* Display nothing when there is no text */ :host([text=""]) #tip { display: none; } p { display: none; align-items: center; justify-content: center; position: absolute; background: #000000C0; width: max-content; min-width: 100px; height: 40px; text-align: center; vertical-align: middle; font-size: 18px; font-weight: var(--font-medium); color: #FAFAFA; padding: 0; margin: 0; transform: translateX(-50%); left: var(--tooltip-x); top: var(--tooltip-y); /* Obsidian Styling */ box-sizing: border-box; animation: pop-down 200ms forwards ease-in-out; box-shadow: 0 2px 8px var(--background-modifier-box-shadow); border-radius: var(--radius-s); line-height: var(--line-height-tight); z-index: var(--layer-tooltip); pointer-events: none; word-break: normal; overflow-wrap: anywhere; } `; let ToolTip = class ToolTip extends LitElement { constructor() { super(...arguments); this._trigger = "manual"; this.display = false; this.text = ''; /** * Clamps the tooltip position to within the bounds */ this.clampPosition = (pos, bounds) => { if (!this.textEl || !bounds) return { x: 0, y: 0 }; // Get tooltip bounds let tooltipWidth = this.textEl.offsetWidth; let tooltipHeight = this.textEl.offsetHeight; // Set tooltip position left or right side of mouse based on whether cursor is halfway let leftPosition = pos.x - bounds.left > bounds.width / 2 ? pos.x - bounds.left - 56 : pos.x - bounds.left + 64; let halfTooltipWidth = tooltipWidth / 2; // Clamp to left edge if (leftPosition < 0 + halfTooltipWidth) leftPosition = 0 + halfTooltipWidth; else if (leftPosition + tooltipWidth > bounds.width + halfTooltipWidth) leftPosition = bounds.width - tooltipWidth + halfTooltipWidth; // Get cursor position & align tooltip centered to cursor (1/4 tooltip height) let topPosition = pos.y - bounds.top - tooltipHeight / 4; // Clamp to top edge if (topPosition < 0) topPosition = 0; // Clamp to bottom edge else if (topPosition + tooltipHeight > bounds.height) topPosition = bounds.height - tooltipHeight; return { x: leftPosition, y: topPosition }; }; } set trigger(val) { this._trigger = val; if (val === 'hover') this.display = true; } get trigger() { return this._trigger; } render() { return html ` <slot @click=${() => this.trigger === 'click' ? this.display = !this.display : null} > </slot> <p id="tip"> ${this.text} </p> `; } setClampedPosition({ x, y }, bounds) { this.setPosition(this.clampPosition({ x, y }, bounds)); } setPosition({ x, y }) { this.style.setProperty('--tooltip-x', `${x}px`); this.style.setProperty('--tooltip-y', `${y}px`); } }; ToolTip.styles = styles; __decorate([ query('p') ], ToolTip.prototype, "textEl", void 0); __decorate([ property({ type: Boolean, reflect: true, useDefault: true }) ], ToolTip.prototype, "display", void 0); __decorate([ property({ type: String, reflect: true }) ], ToolTip.prototype, "trigger", null); __decorate([ property({ type: String, reflect: true }) ], ToolTip.prototype, "text", void 0); ToolTip = __decorate([ condCustomElement('tool-tip') ], ToolTip); export { ToolTip };