UNPKG

@kelvininc/ui-components

Version:
104 lines (98 loc) 6.09 kB
import { r as registerInstance, c as createEvent, h } from './index-BOTigrTZ.js'; import { s as ETabItemType, l as EBadgeType, u as ETagState } from './wizard.types-COrzvkrr.js'; import { i as isEmpty } from './isEmpty-DYR6-7ab.js'; import './isObject-Dkd2PDJ-.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 = class { constructor(hostRef) { registerInstance(this, hostRef); 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"] }; } }; KvTabNavigation.style = tabNavigationCss; export { KvTabNavigation as kv_tab_navigation };