@trimble-oss/moduswebcomponents
Version:
Modus Web Components is a modern, accessible UI library built with Stencil JS that provides reusable web components following Trimble's Modus design system. This updated version focuses on improved flexibility, enhanced theming options, comprehensive cust
240 lines (236 loc) • 10.8 kB
JavaScript
import { p as proxyCustomElement, H, d as createEvent, h, c as Host } from './p-X1tirp06.js';
import { i as inheritAriaAttributes } from './p-VPqXjOQn.js';
import { c as createPopper } from './p-BfP9ezJQ.js';
const modusWcTooltipCss = ".modus-wc-tooltip-content{background-color:var(--modus-wc-color-neutral-content);border-radius:0.25rem;color:var(--modus-wc-color-neutral);font-size:0.875rem;font-weight:var(--modus-wc-font-weight-regular);max-width:20rem;overflow-wrap:break-word;padding:0.25rem 0.5rem;pointer-events:none;position:relative;text-align:center;white-space:normal;width:max-content;word-break:break-word;z-index:1000}.modus-wc-tooltip-arrow,.modus-wc-tooltip-arrow::before{background:inherit;height:8px;position:absolute;width:8px}.modus-wc-tooltip-arrow{text-align:initial;visibility:hidden}.modus-wc-tooltip-arrow::before{background-color:var(--modus-wc-color-neutral-content);content:\"\";transform:rotate(45deg);visibility:visible}.modus-wc-tooltip-content[data-popper-placement^=top] .modus-wc-tooltip-arrow{bottom:-4px}.modus-wc-tooltip-content[data-popper-placement^=bottom] .modus-wc-tooltip-arrow{top:-4px}.modus-wc-tooltip-content[data-popper-placement^=left] .modus-wc-tooltip-arrow{right:-4px}.modus-wc-tooltip-content[data-popper-placement^=right] .modus-wc-tooltip-arrow{left:-4px}[data-theme=modus-classic-light] .modus-wc-tooltip-content{background-color:var(--modus-wc-color-gray-7);color:var(--modus-wc-color-white)}[data-theme=modus-classic-light] .modus-wc-tooltip-arrow::before{background-color:var(--modus-wc-color-gray-7)}[data-theme=modus-classic-dark] .modus-wc-tooltip-content{background-color:var(--modus-wc-color-gray-0);color:var(--modus-wc-color-trimble-gray)}[data-theme=modus-classic-dark] .modus-wc-tooltip-arrow::before{background-color:var(--modus-wc-color-gray-0)}[data-theme=connect-light] .modus-wc-tooltip-content,[data-theme=connect-dark] .modus-wc-tooltip-content{background-color:var(--modus-wc-color-base-content);color:var(--modus-wc-color-base-page)}[data-theme=connect-light] .modus-wc-tooltip-arrow::before,[data-theme=connect-dark] .modus-wc-tooltip-arrow::before{background-color:var(--modus-wc-color-base-content)}";
const ModusWcTooltip = /*@__PURE__*/ proxyCustomElement(class ModusWcTooltip extends H {
constructor() {
super();
this.__registerHost();
this.dismissEscape = createEvent(this, "dismissEscape");
this.inheritedAttributes = {};
this.popperInstance = null;
this.tooltipElement = null;
this.triggerElement = null;
/** The text content of the tooltip. */
this.content = '';
/** Custom CSS class to apply to the inner div. */
this.customClass = '';
/** Disables displaying the tooltip on hover */
this.disabled = false;
/** The position that the tooltip will render in relation to the element. */
this.position = 'auto';
/** Track if tooltip was dismissed with Escape key */
this.escapeDismissed = false;
/** Track if tooltip is currently visible */
this.isVisible = false;
this.handleWindowResize = () => {
if (this.popperInstance && this.isVisible) {
void this.popperInstance.update();
}
};
this.handleWindowScroll = () => {
if (this.popperInstance && this.isVisible) {
void this.popperInstance.update();
}
};
}
componentWillLoad() {
this.inheritedAttributes = inheritAriaAttributes(this.el);
}
elementKeyupHandler(event) {
switch (event.code) {
case 'Escape': {
// Allow Escape to dismiss tooltip when it's visible
// When forceOpen is true, Escape should NOT dismiss it
if (this.isVisible && !this.forceOpen) {
this.escapeDismissed = true;
this.dismissEscape.emit();
this.hideTooltip();
}
break;
}
}
}
componentDidLoad() {
this.triggerElement = this.el.querySelector('div > :first-child');
this.tooltipElement = document.createElement('div');
this.tooltipElement.className = `modus-wc-tooltip-content ${this.customClass || ''}`;
this.tooltipElement.textContent = this.content;
this.tooltipElement.setAttribute('role', 'tooltip');
if (this.tooltipId) {
this.tooltipElement.id = this.tooltipId;
}
const arrow = document.createElement('div');
arrow.className = 'modus-wc-tooltip-arrow';
this.tooltipElement.appendChild(arrow);
document.body.appendChild(this.tooltipElement);
this.tooltipElement.style.display = 'none';
if (this.triggerElement && this.tooltipElement) {
this.initializePopper();
}
if (this.forceOpen && !this.disabled && !this.escapeDismissed) {
this.showTooltip();
}
}
disconnectedCallback() {
if (this.popperInstance) {
this.popperInstance.destroy();
this.popperInstance = null;
}
if (this.tooltipElement && document.body.contains(this.tooltipElement)) {
document.body.removeChild(this.tooltipElement);
}
window.removeEventListener('resize', this.handleWindowResize);
window.removeEventListener('scroll', this.handleWindowScroll, true);
}
initializePopper() {
if (!this.triggerElement || !this.tooltipElement)
return;
const placement = this.position === 'auto' ? 'top' : this.position;
const arrowElement = this.tooltipElement.querySelector('.modus-wc-tooltip-arrow');
this.popperInstance = createPopper(this.triggerElement, this.tooltipElement, {
placement,
strategy: 'absolute',
modifiers: [
{
name: 'offset',
options: {
offset: [0, 8],
},
},
{
name: 'preventOverflow',
options: {
padding: 8,
boundary: 'viewport',
},
},
{
name: 'flip',
options: {
fallbackPlacements: ['top', 'right', 'bottom', 'left'],
padding: 8,
boundary: 'viewport',
},
},
{
name: 'arrow',
options: {
element: arrowElement,
padding: 5,
},
},
{
name: 'computeStyles',
options: {
adaptive: true,
gpuAcceleration: true,
},
},
{
name: 'eventListeners',
options: {
scroll: true,
resize: true,
},
},
],
});
window.addEventListener('resize', this.handleWindowResize);
window.addEventListener('scroll', this.handleWindowScroll, true);
}
showTooltip() {
if (this.disabled || this.escapeDismissed || !this.tooltipElement)
return;
this.tooltipElement.style.display = 'block';
this.isVisible = true;
if (this.popperInstance) {
void this.popperInstance.update();
// Force a second update after a short delay to ensure arrow positioning
setTimeout(() => {
if (this.popperInstance) {
void this.popperInstance.update();
}
}, 10);
}
}
hideTooltip() {
if (!this.tooltipElement)
return;
if (!this.forceOpen || this.escapeDismissed) {
this.tooltipElement.style.display = 'none';
this.isVisible = false;
}
}
handlePositionChange() {
if (this.popperInstance) {
void this.popperInstance.setOptions({
placement: this.position === 'auto' ? 'top' : this.position,
});
void this.popperInstance.update();
}
}
handleContentChange(newContent) {
if (this.tooltipElement) {
const arrow = this.tooltipElement.querySelector('.modus-wc-tooltip-arrow');
this.tooltipElement.textContent = newContent;
if (arrow) {
this.tooltipElement.appendChild(arrow);
}
}
}
handleForceOpenChange(forceOpen) {
if (forceOpen && !this.disabled) {
this.showTooltip();
}
else {
this.hideTooltip();
}
}
handleMouseEnter() {
this.escapeDismissed = false;
this.showTooltip();
}
handleMouseLeave() {
if (!this.forceOpen) {
this.hideTooltip();
}
}
render() {
return (h(Host, { key: '028f22dad1fdd4537bd012847d785b8d518d55b2' }, h("div", Object.assign({ key: '9638d7b4536e70c3a38ee3c7b81d27a69effd148', "aria-describedby": this.tooltipId, id: this.tooltipId }, this.inheritedAttributes), h("slot", { key: '326d59ea026f46496671e1eb4238ae59d6ec320d' }))));
}
get el() { return this; }
static get watchers() { return {
"position": ["handlePositionChange"],
"content": ["handleContentChange"],
"forceOpen": ["handleForceOpenChange"]
}; }
static get style() { return modusWcTooltipCss; }
}, [4, "modus-wc-tooltip", {
"content": [1],
"customClass": [1, "custom-class"],
"disabled": [4],
"forceOpen": [4, "force-open"],
"tooltipId": [1, "tooltip-id"],
"position": [1],
"escapeDismissed": [32],
"isVisible": [32]
}, [[4, "keyup", "elementKeyupHandler"], [1, "mouseenter", "handleMouseEnter"], [1, "mouseleave", "handleMouseLeave"]], {
"position": ["handlePositionChange"],
"content": ["handleContentChange"],
"forceOpen": ["handleForceOpenChange"]
}]);
function defineCustomElement() {
if (typeof customElements === "undefined") {
return;
}
const components = ["modus-wc-tooltip"];
components.forEach(tagName => { switch (tagName) {
case "modus-wc-tooltip":
if (!customElements.get(tagName)) {
customElements.define(tagName, ModusWcTooltip);
}
break;
} });
}
export { ModusWcTooltip as M, defineCustomElement as d };