@kelvininc/ui-components
Version:
Kelvin UI Components
154 lines (147 loc) • 7.9 kB
JavaScript
import { H as proxyCustomElement, I as H, J as createEvent, x as ETabItemType, K as h, o as EBadgeType, z as ETagState } from './p-BP5CxQcH.js';
import { d as defineCustomElement$5 } from './p-CJTppmYq.js';
import { d as defineCustomElement$4 } from './p-DQ7v6WT-.js';
import { d as defineCustomElement$3 } from './p-Dx7sxQCt.js';
import { d as defineCustomElement$2 } from './p-hhSEa0Xf.js';
import { i as isEmpty } from './p-BZNGlO8m.js';
const TEXT_FONT_DESCRIPTION = '600 16px Proxima Nova';
const BADGE_FONT_DESCRIPTION = '400 14px Proxima Nova';
const BADGE_PADDING_PX = 8;
const TAB_ITEM_PADDING_PX = 48;
const TAB_ITEM_GAP_PX = 8;
const TAB_ITEM_ICON_WIDTH_PX = 16;
const calculatePrimaryTabWidths = async (tabs) => {
await document.fonts.load(TEXT_FONT_DESCRIPTION);
await document.fonts.load(BADGE_FONT_DESCRIPTION);
const textMeasuringCanvas = document.createElement('canvas');
const textCtx = textMeasuringCanvas.getContext('2d');
textCtx.font = TEXT_FONT_DESCRIPTION;
const badgeMeasuringCanvas = document.createElement('canvas');
const badgeCtx = badgeMeasuringCanvas.getContext('2d');
badgeCtx.font = BADGE_FONT_DESCRIPTION;
const values = tabs.reduce((acc, { tabKey, label, tagIcon, badge }, idx) => {
const previousTab = idx > 0 ? tabs[idx - 1] : undefined;
const leftOffset = previousTab ? +acc[previousTab.tabKey].width + +acc[previousTab.tabKey].left : 0;
const tagIconWidth = tagIcon ? TAB_ITEM_ICON_WIDTH_PX + TAB_ITEM_GAP_PX : 0;
const textWidth = Math.round(textCtx.measureText(label).width);
const badgeWidth = badge ? Math.round(badgeCtx.measureText(badge).width) + BADGE_PADDING_PX + TAB_ITEM_GAP_PX : 0;
acc[tabKey] = {
left: `${leftOffset}`,
width: `${textWidth + TAB_ITEM_PADDING_PX + tagIconWidth + badgeWidth}`
};
return acc;
}, {});
return values;
};
const tabNavigationCss = "@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{--tab-list-bg-color:transparent;--tab-list-indicator-color:var(--tab-primary-border-color-selected);--tab-list-divider-color:var(--tab-primary-border-color-default);--secondary-tab-list-direction:row;--secondary-items-align:center}:host .primary{position:relative;width:100%;display:flex;background-color:var(--tab-list-bg-color)}:host .primary::before{content:\"\";width:100%;position:absolute;bottom:0;border-bottom:var(--tab-primary-border-thickness-default) solid var(--tab-list-divider-color)}:host .primary .selected-tab-indicator{height:var(--tab-primary-border-thickness-strong);position:absolute;bottom:0;transition:all 0.3s ease-out;background:var(--tab-list-indicator-color)}:host .secondary{display:flex;gap:var(--spacing-xl);align-items:var(--secondary-items-align);flex-direction:var(--secondary-tab-list-direction)}:host kv-badge{--badge-height:var(--size-md)}:host kv-tag-status{--tag-status-icon-size:var(--size-md)}";
const KvTabNavigation$1 = /*@__PURE__*/ proxyCustomElement(class KvTabNavigation extends H {
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.tabChange = createEvent(this, "tabChange", 7);
/** @inheritdoc */
this.tabs = [];
/** @inheritdoc */
this.type = ETabItemType.Primary;
this.tabsIndicatorConfig = {};
/** The left offset and width of the tab indicator, recalculated when the selected tab changes */
this.selectedTabIndicatorConfig = {
left: '0px',
width: '0px'
};
}
/** Listen to custom DOM event of tab selection */
tabSelectionHandler(event) {
this.tabChange.emit(event.detail);
}
/** Watch for tabs change to calculate elements width */
async tabsChangeHandler() {
if (this.type === ETabItemType.Primary) {
this.tabsIndicatorConfig = await calculatePrimaryTabWidths(this.tabs);
this.applySelectedTabStyling();
}
}
/** Watch for tab selection change and react accordingly by updating the internal states */
async tabSelectionChangeHandler() {
if (this.type === ETabItemType.Secondary)
return;
if (isEmpty(this.tabsIndicatorConfig)) {
this.tabsIndicatorConfig = await calculatePrimaryTabWidths(this.tabs);
}
this.applySelectedTabStyling();
}
async componentDidLoad() {
if (this.type === ETabItemType.Primary) {
this.tabsIndicatorConfig = await calculatePrimaryTabWidths(this.tabs);
this.applySelectedTabStyling();
}
}
applySelectedTabStyling() {
if (isEmpty(this.selectedTabKey) || isEmpty(this.tabsIndicatorConfig[this.selectedTabKey]))
return;
const { left, width } = this.tabsIndicatorConfig[this.selectedTabKey];
this.selectedTabIndicatorConfig = {
left: `${left}px`,
width: `${width}px`
};
}
render() {
return (h("div", { key: '5d92049120e60dfb35381b6caece9453c3297c79', class: { [this.type]: true } }, this.tabs.map(item => {
var _a, _b;
return (h("kv-tab-item", { key: item.tabKey, tabKey: item.tabKey, label: item.label, icon: item.icon, disabled: item.disabled, selected: item.tabKey === this.selectedTabKey, type: this.type, customAttributes: item.customAttributes }, (!isEmpty(item.badge) || !isEmpty(item.tagIcon)) && (h("div", { slot: "right-slot" }, !isEmpty(item.badge) && h("kv-badge", { type: (_a = item.badgeType) !== null && _a !== void 0 ? _a : EBadgeType.Secondary }, item.badge), !isEmpty(item.tagIcon) && h("kv-tag-status", { icon: item.tagIcon, state: (_b = item.tagState) !== null && _b !== void 0 ? _b : ETagState.Unknown })))));
}), this.type === ETabItemType.Primary && h("div", { key: '0d8efc09b49d09b7d3c9da1810bb82f3a99eeb0d', class: "selected-tab-indicator", style: this.selectedTabIndicatorConfig })));
}
static get watchers() { return {
"tabs": ["tabsChangeHandler"],
"type": ["tabsChangeHandler"],
"selectedTabKey": ["tabSelectionChangeHandler"]
}; }
static get style() { return tabNavigationCss; }
}, [257, "kv-tab-navigation", {
"tabs": [16],
"selectedTabKey": [8, "selected-tab-key"],
"type": [1],
"selectedTabIndicatorConfig": [32]
}, [[0, "tabSelected", "tabSelectionHandler"]], {
"tabs": ["tabsChangeHandler"],
"type": ["tabsChangeHandler"],
"selectedTabKey": ["tabSelectionChangeHandler"]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["kv-tab-navigation", "kv-badge", "kv-icon", "kv-tab-item", "kv-tag-status"];
components.forEach(tagName => { switch (tagName) {
case "kv-tab-navigation":
if (!customElements.get(tagName)) {
customElements.define(tagName, KvTabNavigation$1);
}
break;
case "kv-badge":
if (!customElements.get(tagName)) {
defineCustomElement$5();
}
break;
case "kv-icon":
if (!customElements.get(tagName)) {
defineCustomElement$4();
}
break;
case "kv-tab-item":
if (!customElements.get(tagName)) {
defineCustomElement$3();
}
break;
case "kv-tag-status":
if (!customElements.get(tagName)) {
defineCustomElement$2();
}
break;
} });
}
defineCustomElement$1();
const KvTabNavigation = KvTabNavigation$1;
const defineCustomElement = defineCustomElement$1;
export { KvTabNavigation, defineCustomElement };