@alegendstale/holly-components
Version:
Reusable UI components created using lit
145 lines (137 loc) • 4.78 kB
JavaScript
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
=${() => 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 };