UNPKG

@kit-data-manager/pid-component

Version:

The PID-Component is a web component that can be used to evaluate and display FAIR Digital Objects, PIDs, ORCiDs, and possibly other identifiers in a user-friendly way. It is easily extensible to support other identifier types.

217 lines (214 loc) 10.7 kB
/*! * * Copyright 2024 Karlsruhe Institute of Technology. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { p as proxyCustomElement, H, c as createEvent, h, a as Host } from './index.js'; const PidTooltip = proxyCustomElement(class PidTooltip extends H { constructor() { super(); this.__registerHost(); this.tooltipExpansionChange = createEvent(this, "tooltipExpansionChange"); this.isVisible = false; this.calculatedPosition = 'top'; this.needsRowExpansion = false; this.tooltipId = `tooltip-${Math.random().toString(36).substring(2, 11)}`; this.showTooltip = () => { this.isVisible = true; setTimeout(() => this.calculateOptimalPosition(), 10); }; this.hideTooltip = () => { this.isVisible = false; this.restoreRowHeight(); }; this.toggleTooltip = (event) => { event.preventDefault(); event.stopPropagation(); if (this.isVisible) { this.hideTooltip(); } else { this.showTooltip(); } }; this.handleButtonKeyDown = (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.toggleTooltip(event); } }; this.position = 'top'; this.maxWidth = '250px'; this.maxHeight = '150px'; this.fitContent = true; } handleKeyDown(event) { var _a; if (event.key === 'Escape' && this.isVisible) { this.hideTooltip(); (_a = this.buttonRef) === null || _a === void 0 ? void 0 : _a.focus(); event.preventDefault(); event.stopPropagation(); } } componentDidLoad() { this.calculatedPosition = this.position === 'bottom' ? 'bottom' : 'top'; this.tableRow = this.el.closest('tr'); } calculateOptimalPosition() { if (!this.tooltipRef || !this.isVisible) return; const hostRect = this.el.getBoundingClientRect(); const table = this.el.closest('table'); const tableContainer = (table === null || table === void 0 ? void 0 : table.closest('.overflow-auto')) || (table === null || table === void 0 ? void 0 : table.parentElement); if (!tableContainer) { this.calculatedPosition = this.position === 'bottom' ? 'bottom' : 'top'; return; } const containerRect = tableContainer.getBoundingClientRect(); const spaceAbove = hostRect.top - containerRect.top; const spaceBelow = containerRect.bottom - hostRect.bottom; const tooltipHeight = this.estimateTooltipHeight(this.text); const requiredSpace = tooltipHeight + 20; let useBottom; let needsExpansion = false; if (this.position === 'top' && spaceAbove >= requiredSpace) { useBottom = false; } else if (this.position === 'bottom' && spaceBelow >= requiredSpace) { useBottom = true; } else if (spaceAbove >= spaceBelow && spaceAbove >= requiredSpace) { useBottom = false; } else if (spaceBelow >= requiredSpace) { useBottom = true; } else { useBottom = true; needsExpansion = true; } this.calculatedPosition = useBottom ? 'bottom' : 'top'; this.needsRowExpansion = needsExpansion; if (needsExpansion) { this.expandRowForTooltip(tooltipHeight); } } expandRowForTooltip(tooltipHeight) { if (!this.tableRow) return; this.originalRowHeight = this.tableRow.style.height || 'auto'; const currentRowHeight = this.tableRow.offsetHeight; const requiredAdditionalHeight = tooltipHeight + 40; const newRowHeight = Math.max(currentRowHeight, requiredAdditionalHeight); this.tableRow.style.transition = 'height 0.2s ease-in-out'; this.tableRow.style.height = `${newRowHeight}px`; this.tooltipExpansionChange.emit({ expand: true, requiredHeight: newRowHeight, }); } restoreRowHeight() { if (!this.tableRow || !this.needsRowExpansion) return; this.tableRow.style.height = this.originalRowHeight || 'auto'; setTimeout(() => { if (this.tableRow) { this.tableRow.style.transition = ''; } }, 200); this.needsRowExpansion = false; this.tooltipExpansionChange.emit({ expand: false, requiredHeight: 0, }); } estimateTooltipHeight(content) { const tempDiv = document.createElement('div'); tempDiv.setAttribute('aria-hidden', 'true'); tempDiv.setAttribute('tabindex', '-1'); tempDiv.setAttribute('role', 'presentation'); tempDiv.style.cssText = ` position: absolute; visibility: hidden; white-space: normal; word-wrap: break-word; max-width: ${this.maxWidth}; padding: 12px; font-size: 12px; line-height: 1.4; border: 1px solid transparent; pointer-events: none; `; tempDiv.textContent = content; document.body.appendChild(tempDiv); const height = tempDiv.offsetHeight; document.body.removeChild(tempDiv); return height; } render() { const hasTooltipText = this.text && this.text.trim().length > 0; const buttonLabel = `${this.isVisible ? 'Hide' : 'Show'} additional information`; const parentComponent = this.el.closest('pid-component'); const isDarkMode = parentComponent === null || parentComponent === void 0 ? void 0 : parentComponent.classList.contains('bg-gray-800'); return (h(Host, { key: 'e5295dae6fd443a5e80d135856c15ffc9059c2a9', class: "relative inline-block w-full", onMouseEnter: this.showTooltip, onMouseLeave: this.hideTooltip }, this.isVisible && (h("span", { key: '0588790c20ca97b641ec56111699299e0482d789', class: "sr-only", "aria-live": "assertive" }, "Information tooltip opened")), h("div", { key: '940287de8471434bd5af374f1415c21708f5d463', class: "flex items-center justify-between" }, h("slot", { key: '9dbc804a3e610f7d9da8cba2e4d8e665d949dbf1', name: "trigger" }), hasTooltipText && (h("button", { key: '0c3a92bb782d9103459ffcee4dff8cfa9c33a6e5', ref: el => (this.buttonRef = el), type: "button", class: `flex items-center rounded-full p-0.5 transition-colors duration-200 ${isDarkMode ? 'text-gray-300 hover:bg-gray-700' : 'text-gray-600 hover:bg-gray-100'} focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 focus:outline-none`, "aria-label": buttonLabel, "aria-expanded": this.isVisible ? 'true' : 'false', "aria-controls": this.tooltipId, "aria-describedby": this.isVisible ? this.tooltipId : undefined, onClick: this.toggleTooltip, onKeyDown: this.handleButtonKeyDown, onFocus: this.showTooltip, onBlur: this.hideTooltip, tabIndex: 0, title: buttonLabel }, h("svg", { key: '74331fad1f2b9fa53fffe60039abc8ac82059b27', "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", class: "icon icon-tabler icon-tabler-info-circle min-h-[1rem] min-w-[1rem] flex-shrink-0", width: "20", height: "20", viewBox: "0 0 24 24", "stroke-width": "1.5", stroke: "currentColor", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round", role: "img" }, h("title", { key: '428499e9aac7b8e13db66edc0c86a367e3ec2d33' }, "Information icon"), h("desc", { key: '887352ca3b10a544a85ba909fabc05eb21d49f81' }, "An icon indicating additional information is available"), h("path", { key: '197e29a49e404230c066b5d5ece4ec58b122696b', stroke: "none", d: "M0 0h24v24H0z" }), h("circle", { key: '537678517fc043d41c78dc0bf97e41fcc62b8503', cx: "12", cy: "12", r: "9" }), h("line", { key: '2878419c9d3a7c525ed9931400159efe664ecb00', x1: "12", y1: "8", x2: "12.01", y2: "8" }), h("polyline", { key: 'c5ac63bf54a34d688608118f9689c8fcaa7ec70b', points: "11 12 12 12 12 16 13 16" }))))), hasTooltipText && (h("div", { key: '6c2b225b019329683ed3254a2fd6237e20b2f4e4', ref: el => (this.tooltipRef = el), id: this.tooltipId, role: "tooltip", class: `${this.isVisible ? 'block' : 'hidden'} absolute z-50 ${this.getPositionClasses(this.calculatedPosition)} w-full rounded border ${isDarkMode ? 'border-gray-600 bg-gray-700 text-gray-200' : 'border-gray-300 bg-white text-gray-700'} p-3 text-xs whitespace-normal shadow-lg transition-opacity duration-200 ease-in-out`, style: this.getTooltipStyles(), "aria-live": "polite" }, h("p", { key: 'd7762cb0aa9405e3836839a39787545c86477df8', class: "m-0 p-0" }, this.text))))); } getPositionClasses(position) { switch (position) { case 'top': return 'bottom-full left-0 mb-2'; case 'bottom': return 'top-full left-0 mt-2'; default: return 'top-full left-0 mt-2'; } } getTooltipStyles() { const styles = { maxWidth: this.maxWidth, }; if (this.needsRowExpansion || !this.fitContent) { styles.maxHeight = this.maxHeight; styles.overflowY = 'auto'; } return styles; } get el() { return this; } }, [4, "pid-tooltip", { "text": [1], "position": [1], "maxWidth": [1, "max-width"], "maxHeight": [1, "max-height"], "fitContent": [4, "fit-content"], "isVisible": [32], "calculatedPosition": [32], "needsRowExpansion": [32] }, [[0, "keydown", "handleKeyDown"]]]); function defineCustomElement() { if (typeof customElements === "undefined") { return; } const components = ["pid-tooltip"]; components.forEach(tagName => { switch (tagName) { case "pid-tooltip": if (!customElements.get(tagName)) { customElements.define(tagName, PidTooltip); } break; } }); } export { PidTooltip as P, defineCustomElement as d }; //# sourceMappingURL=p-Dp5xdayO.js.map //# sourceMappingURL=p-Dp5xdayO.js.map