@kelvininc/ui-components
Version:
Kelvin UI Components
331 lines (321 loc) • 15 kB
JavaScript
import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-BOTigrTZ.js';
import { o as offset, b as shift, c as arrow, h as hide, d as computePosition, e as autoUpdate, a as autoPlacement } from './floating-ui.dom-CJTtq_QG.js';
import { b as DEFAULT_PORTAL_Z_INDEX, c as TOOLTIP_Z_INDEX } from './config-DfTrc9q6.js';
import { m as mergeComputePositionConfigs } from './floating-ui.helper-BoQ1sJsH.js';
import { i as isNil } from './isNil-DjSNdVAB.js';
import { b as getCollapsedElement } from './utils-Douu2-ri.js';
import { a as getClassMap } from './css-class.helper-DCOsOAOy.js';
import { i as isEmpty } from './isEmpty-DYR6-7ab.js';
import './wizard.types-COrzvkrr.js';
import './_baseMerge-ECDD_Loo.js';
import './identity-CK4jS9_E.js';
import './isObject-Dkd2PDJ-.js';
import './_setToArray-WfAeX5vN.js';
const PORTAL_Z_INDEX = {
hidden: -1,
show: DEFAULT_PORTAL_Z_INDEX
};
const OFFSET_WITH_ARROW = 10;
const STATIC_SIDE_OFFSET = '-5px';
const getArrowElementPositionConfig = (x, y, placement) => {
const staticSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right'
}[placement.split('-')[0]];
return {
left: x != null ? `${x}px` : '',
top: y != null ? `${y}px` : '',
right: '',
bottom: '',
[staticSide]: STATIC_SIDE_OFFSET,
transform: 'rotate(45deg)'
};
};
const DEFAULT_OFFSET = 5;
const DEFAULT_SHIFT_CONFIG = {
padding: 5
};
const portalCss = "@property --rotation{syntax:\"<angle>\";initial-value:0deg;inherits:false}@keyframes rotate-border{to{--rotation:360deg}}kv-dropdown-base:not(.hydrated)>[slot=list]{display:none}:host{--portal-arrow-color:var(--tooltip-background-default)}.portal-container{visibility:hidden;opacity:0}.portal-container--visible{visibility:visible;opacity:1}.portal-container--visible.portal-container--animated{transition:opacity 0.3s linear}.portal-container .portal-arrow{position:absolute;background:var(--portal-arrow-color);width:10px;height:10px}";
const KvPortal = class {
constructor(hostRef) {
registerInstance(this, hostRef);
this.elementAppend = createEvent(this, "elementAppend", 7);
/** @inheritdoc */
this.portalId = 'kv-portal';
/** @inheritdoc */
this.show = false;
/** @inheritdoc */
this.autoUpdate = true;
/** @inheritdoc */
this.animated = false;
/** @inheritdoc */
this.withArrow = false;
/** @inheritdoc */
this.delay = 0;
/** @inheritdoc */
this.zIndex = PORTAL_Z_INDEX.show;
this.visible = false;
this.moved = false;
this.getPortalArrowElement = () => {
return this.element.shadowRoot.querySelector('#portal-arrow');
};
this.getMiddlewareConfig = () => {
const arrowElement = this.getPortalArrowElement();
const offSet = this.withArrow ? OFFSET_WITH_ARROW : DEFAULT_OFFSET;
const middleware = [offset(offSet), shift(DEFAULT_SHIFT_CONFIG)];
if (this.withArrow)
middleware.push(arrow({ element: arrowElement, padding: 5 }));
middleware.push(hide({ padding: 15 }));
return middleware;
};
this.getOptions = () => {
const middleware = this.getMiddlewareConfig();
return mergeComputePositionConfigs({ middleware }, this.options);
};
}
showWatch(newValue) {
if (newValue) {
this.showPortalContent();
}
else {
this.hidePortalContent();
}
}
referenceWatch() {
if (this.show) {
this.showPortalContent();
}
}
getClosestThemedAncestor() {
let current = this.element;
while (current) {
const themed = current.closest('[data-theme]');
if (themed)
return themed;
const root = current.getRootNode();
current = root instanceof ShadowRoot ? root.host : null;
}
return null;
}
createPortal() {
this.portal = document.createElement('div');
this.portal.setAttribute('id', this.portalId);
this.portal.style.zIndex = `${PORTAL_Z_INDEX.hidden}`;
this.portal.style.position = 'absolute';
// Inherit data-theme from nearest themed ancestor so portal
// content resolves the correct design token values.
// Traverse shadow DOM boundaries since the portal may be
// rendered inside another component's shadow tree (e.g. tooltip).
const themedAncestor = this.getClosestThemedAncestor();
const theme = themedAncestor === null || themedAncestor === void 0 ? void 0 : themedAncestor.getAttribute('data-theme');
if (theme) {
this.portal.setAttribute('data-theme', theme);
}
document.body.prepend(this.portal);
}
moveElementToPortal() {
this.portal.appendChild(this.element);
this.elementAppend.emit(this.element);
}
updatePosition() {
computePosition(this.reference, this.portal, this.getOptions()).then(({ x, y, placement, middlewareData }) => {
if (this.autoUpdate) {
const { referenceHidden } = middlewareData.hide;
if (this.show) {
this.visible = !referenceHidden;
this.portal.style.zIndex = referenceHidden ? `${PORTAL_Z_INDEX.hidden}` : `${this.zIndex}`;
}
}
Object.assign(this.portal.style, {
left: `${x}px`,
top: `${y}px`
});
if (this.withArrow) {
const { x: arrowX, y: arrowY } = middlewareData.arrow;
Object.assign(this.getPortalArrowElement().style, Object.assign({}, getArrowElementPositionConfig(arrowX, arrowY, placement)));
}
});
}
calculatePosition() {
if (!this.reference || !this.portal) {
return;
}
if (this.autoUpdate) {
this.closeAutoUpdate = autoUpdate(this.reference, this.portal, () => this.updatePosition());
}
else {
this.updatePosition();
}
}
showPortalContent() {
if (!this.portal)
return;
this.portal.style.zIndex = `${this.zIndex}`;
if (this.delay) {
this.timeoutId = window.setTimeout(() => {
this.visible = true;
this.calculatePosition();
}, this.delay);
}
else {
this.visible = true;
this.calculatePosition();
}
}
hidePortalContent() {
this.visible = false;
this.portal.style.zIndex = `${PORTAL_Z_INDEX.hidden}`;
if (this.timeoutId) {
window.clearTimeout(this.timeoutId);
this.timeoutId = undefined;
}
if (!isNil(this.closeAutoUpdate)) {
this.closeAutoUpdate();
}
}
componentWillLoad() {
this.createPortal();
}
componentDidLoad() {
this.moveElementToPortal();
if (this.show) {
this.showPortalContent();
}
}
disconnectedCallback() {
var _a;
this.moved ? (_a = this.portal) === null || _a === void 0 ? void 0 : _a.remove() : (this.moved = true);
}
render() {
return (h(Host, { key: 'edcd8472eb044ae6d4475cb1f8e63151b831157c' }, h("div", { key: '1ba1eb8760e0104a688235c34a5b3ee6e59fca0b', class: { 'portal-container': true, 'portal-container--animated': this.animated, 'portal-container--visible': this.visible } }, h("slot", { key: '94ed2ad8e45ac3e9287bb5d1dd40eeccfd7fde57' }), this.withArrow && h("div", { key: '04806f60effcb03f57fd7d5344000e9ba3922582', id: "portal-arrow", class: "portal-arrow" }))));
}
get element() { return getElement(this); }
static get watchers() { return {
"show": ["showWatch"],
"reference": ["referenceWatch"]
}; }
};
KvPortal.style = portalCss;
const DEFAULT_POSITION_CONFIG = {
strategy: 'fixed',
middleware: [offset(5), shift({ padding: 5 })]
};
const DEFAULT_HIDE_DELAY = 1000;
const DEFAULT_DELAY_CONFIG = 1000;
const DEFAULT_AUTO_PLACEMENT_CONFIG = {
padding: 5
};
const isElementCollapsed = (element) => {
const collapsedElement = getCollapsedElement(Array.from(element.childNodes));
if (collapsedElement !== undefined) {
const range = new Range();
range.selectNodeContents(collapsedElement);
const { width: rectWidth } = range.getBoundingClientRect();
const { clientWidth: collapsedWidth } = collapsedElement;
// once rectWidth comes as a real value and collapsedWidth as a rounded value, this calculation was incorrect.
if (collapsedWidth >= Math.round(rectWidth))
return false;
}
return true;
};
const KvTooltip = class {
constructor(hostRef) {
registerInstance(this, hostRef);
/** @inheritdoc */
this.text = '';
/** @inheritdoc */
this.options = DEFAULT_POSITION_CONFIG;
/** @inheritdoc */
this.disabled = false;
/** @inheritdoc */
this.contentElement = null;
/** @inheritdoc */
this.truncate = false;
/** @inheritdoc */
this.delay = DEFAULT_DELAY_CONFIG;
/** @inheritdoc */
this.hideDelay = DEFAULT_HIDE_DELAY;
/** @inheritdoc */
this.withArrow = false;
/** @inheritdoc */
this.customClass = '';
this.showTooltip = false;
this.hoverContent = false;
this.hoverTooltip = false;
this.getContentElement = () => {
var _a;
return (_a = this.contentElement) !== null && _a !== void 0 ? _a : this.tooltipContent;
};
this.getOptions = () => {
const placement = isEmpty(this.allowedPositions) ? this.position : undefined;
const middleware = [];
if (!isEmpty(this.allowedPositions) && isEmpty(placement)) {
middleware.push(autoPlacement(Object.assign(Object.assign({}, DEFAULT_AUTO_PLACEMENT_CONFIG), { allowedPlacements: this.allowedPositions })));
}
return mergeComputePositionConfigs({ placement, middleware }, this.options);
};
this.hideTooltipHandler = (delay) => {
if (delay) {
setTimeout(() => {
if (!this.hoverContent && !this.hoverTooltip) {
this.showTooltip = false;
}
}, delay);
return;
}
this.showTooltip = false;
};
this.getTooltipSlotElement = () => {
return this.el.querySelector('[slot="tooltip-text"]');
};
this.showTooltipHandler = () => {
if (this.disabled || (this.truncate && !isElementCollapsed(this.el)))
return;
this.showTooltip = true;
};
}
disconnectedCallback() {
this.showTooltip = false;
}
render() {
const tooltipSlotElement = this.getTooltipSlotElement();
return (h(Host, { key: '8cb12be614c78d1bcf039d1b2199763d97735ee7' }, h("div", { key: '8de03a96446c4b1b84918df22059710f506bf117', id: "content", part: "content", ref: el => (this.tooltipContent = el), onMouseOver: () => {
this.showTooltipHandler();
this.hoverContent = true;
}, onMouseOut: () => {
this.hoverContent = false;
this.hideTooltipHandler(!isEmpty(tooltipSlotElement) ? this.hideDelay : undefined);
}, onBlur: () => {
this.hoverContent = false;
this.hideTooltipHandler(!isEmpty(tooltipSlotElement) ? this.hideDelay : undefined);
}, onClick: () => {
this.hoverContent = false;
this.hideTooltipHandler();
} }, h("slot", { key: 'adab3af0dbba69f4edbc50e708bfc272d9c59fb3' })), h("div", { key: 'e54dcd487a1b667861d556c176836603eb543b90', style: { display: 'none' } }, h("slot", { key: 'd12f4a5caa826634666eab65b2e04828764ca9ca', name: "tooltip-text" })), this.showTooltip && (!isEmpty(this.text) || !isEmpty(tooltipSlotElement)) && (h("kv-portal", { key: 'aee9fbd2781db2a074c93450f34646d357bd6a7c', zIndex: TOOLTIP_Z_INDEX, show: true, delay: this.delay, withArrow: this.withArrow, animated: true, reference: this.getContentElement(), options: this.getOptions() }, h("kv-tooltip-text", { key: '20b1f2e5f44b0c1b5da1d16a6f4f041a4457ae0c', class: Object.assign({}, getClassMap(this.customClass)), text: this.text, style: this.customStyle, onMouseOver: () => {
this.hoverTooltip = true;
this.showTooltipHandler();
}, onMouseOut: () => {
this.hoverTooltip = false;
this.hideTooltipHandler();
}, onBlur: () => {
this.hoverTooltip = false;
this.hideTooltipHandler();
} }, tooltipSlotElement && h("div", { key: 'b4178ca3ede4d6c087eed3f8989909aee5d51c87', innerHTML: tooltipSlotElement.innerHTML }))))));
}
get el() { return getElement(this); }
};
const tooltipTextCss = "@property --rotation{syntax:\"<angle>\";initial-value:0deg;inherits:false}@keyframes rotate-border{to{--rotation:360deg}}kv-dropdown-base:not(.hydrated)>[slot=list]{display:none}:host{--container-white-space:normal;--container-width:fit-content;--container-max-width:280px;--container-background-color:var(--tooltip-background-default)}.tooltip-container{height:fit-content;width:var(--container-width);max-width:var(--container-max-width);display:inline-block;word-wrap:break-word;background-color:var(--container-background-color);user-select:none;border-radius:var(--tooltip-radius-default);padding:var(--tooltip-padding-y-default) var(--tooltip-padding-x-default);white-space:var(--container-white-space)}.tooltip-container .tooltip-text{font-family:Proxima Nova;font-weight:600;font-size:14px;line-height:20px;letter-spacing:0;color:var(--tooltip-text-default)}";
const KvTooltipText = class {
constructor(hostRef) {
registerInstance(this, hostRef);
/** @inheritdoc */
this.text = '';
}
render() {
return (h(Host, { key: '70840ea0de71d12ce34b657f0fdf9d2a940f6332' }, h("div", { key: '4ff2b2e412cb5d3531548915b4885f9eb109524f', class: "tooltip-container", part: "tooltip-container" }, this.text && h("div", { key: 'af8d1f527dbc20d141c1e00ff58f5ebbd320014b', class: "tooltip-text" }, this.text), h("div", { key: 'e5a8a93fc9d3c37615c10e060cb6cc4026dd3b71', class: "tooltip-slot", part: "tooltip-slot-content" }, h("slot", { key: '0e011fc72a7b96a2a4324e1715f679092f11473b' })))));
}
};
KvTooltipText.style = tooltipTextCss;
export { KvPortal as kv_portal, KvTooltip as kv_tooltip, KvTooltipText as kv_tooltip_text };