@brightspot/ui 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/action-bar/ActionBar.d.ts +163 -0
- package/dist/components/action-bar/ActionBar.d.ts.map +1 -0
- package/dist/components/action-bar/ActionBar.js +479 -0
- package/dist/components/action-bar/ActionBar.js.map +1 -0
- package/dist/components/action-bar/ActionItem.d.ts +103 -0
- package/dist/components/action-bar/ActionItem.d.ts.map +1 -0
- package/dist/components/action-bar/ActionItem.js +237 -0
- package/dist/components/action-bar/ActionItem.js.map +1 -0
- package/dist/components/dropdown/Dropdown.d.ts +3 -1
- package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
- package/dist/components/dropdown/Dropdown.js +22 -6
- package/dist/components/dropdown/Dropdown.js.map +1 -1
- package/dist/components/dropdown/DropdownItem.d.ts +14 -1
- package/dist/components/dropdown/DropdownItem.d.ts.map +1 -1
- package/dist/components/dropdown/DropdownItem.js +20 -1
- package/dist/components/dropdown/DropdownItem.js.map +1 -1
- package/dist/components/dropdown/DropdownMenu.d.ts +3 -5
- package/dist/components/dropdown/DropdownMenu.d.ts.map +1 -1
- package/dist/components/dropdown/DropdownMenu.js +17 -32
- package/dist/components/dropdown/DropdownMenu.js.map +1 -1
- package/dist/components/pagination/Pagination.d.ts +33 -4
- package/dist/components/pagination/Pagination.d.ts.map +1 -1
- package/dist/components/pagination/Pagination.js +80 -16
- package/dist/components/pagination/Pagination.js.map +1 -1
- package/dist/components/tabs/Tab.d.ts +108 -0
- package/dist/components/tabs/Tab.d.ts.map +1 -0
- package/dist/components/tabs/Tab.js +152 -0
- package/dist/components/tabs/Tab.js.map +1 -0
- package/dist/components/tabs/Tabs.d.ts +126 -0
- package/dist/components/tabs/Tabs.d.ts.map +1 -0
- package/dist/components/tabs/Tabs.js +390 -0
- package/dist/components/tabs/Tabs.js.map +1 -0
- package/dist/custom-elements.json +2635 -1591
- package/dist/storybook/assets/ActionBar.stories--nAeDC-G.js +408 -0
- package/dist/storybook/assets/ActionItem.stories-BHrGjk-P.js +203 -0
- package/dist/storybook/assets/{Avatar.stories-B26mRkkZ.js → Avatar.stories-Da-mRj6_.js} +1 -1
- package/dist/storybook/assets/{AvatarGroup.stories-J7lVGsMY.js → AvatarGroup.stories-BQlaC_yl.js} +1 -1
- package/dist/storybook/assets/{Badge.stories-BpTIV61M.js → Badge.stories-DnVnOrnF.js} +1 -1
- package/dist/storybook/assets/{Button-Dg-fIrzT.js → Button-CFLAI1H9.js} +1 -1
- package/dist/storybook/assets/{Button.stories-gPKRVbxk.js → Button.stories-DxaBOjwv.js} +1 -1
- package/dist/storybook/assets/{Celebrate.stories-DbY-sKEe.js → Celebrate.stories-CuMm15Nr.js} +1 -1
- package/dist/storybook/assets/{CircularProgress.stories-DeH5JYX_.js → CircularProgress.stories-DRN8Mtvj.js} +1 -1
- package/dist/storybook/assets/{ClipboardMixin.stories-C-lZ4uuw.js → ClipboardMixin.stories-DR7Ou2Av.js} +1 -1
- package/dist/storybook/assets/{Color-6BZIO3FS-Cu6zVIuG.js → Color-6BZIO3FS-Die62Y0Z.js} +1 -1
- package/dist/storybook/assets/{Colors.stories-D6XYMrTD.js → Colors.stories-bIq_ssbI.js} +1 -1
- package/dist/storybook/assets/{CombinedEffects.stories-jFekKTYg.js → CombinedEffects.stories-CtKzOUZn.js} +1 -1
- package/dist/storybook/assets/{ComponentStatesMixin-g50hRCPT.js → ComponentStatesMixin-DMLCk9fE.js} +1 -1
- package/dist/storybook/assets/{ComponentStatesMixin.stories-D3Q5pR38.js → ComponentStatesMixin.stories-D8UI9o-d.js} +1 -1
- package/dist/storybook/assets/{CopyToClipboard.stories-COZZ1VC2.js → CopyToClipboard.stories-ti6CpJNp.js} +1 -1
- package/dist/storybook/assets/{Debounce.stories-Dl10LAnx.js → Debounce.stories-DzZUSvbk.js} +1 -1
- package/dist/storybook/assets/{DocsRenderer-LL677BLK-CFLtMbUx.js → DocsRenderer-LL677BLK-CIRGv5IX.js} +3 -3
- package/dist/storybook/assets/{Dropdown.stories-Drwq-0Z2.js → Dropdown.stories-Lt4cY0Re.js} +41 -14
- package/dist/storybook/assets/{Events.stories-dODeR-g-.js → Events.stories-B1ddcgpT.js} +1 -1
- package/dist/storybook/assets/{Heading.stories-CH7_-_q3.js → Heading.stories-DI4w61cf.js} +1 -1
- package/dist/storybook/assets/{HueRipple.stories-CH1Y739k.js → HueRipple.stories-DjhoxxEw.js} +1 -1
- package/dist/storybook/assets/{Icon.stories-CPjM-jTU.js → Icon.stories-CpziAhae.js} +1 -1
- package/dist/storybook/assets/{IconButton.stories-DuzqvcnN.js → IconButton.stories-KjN28hfc.js} +1 -1
- package/dist/storybook/assets/{LinearProgress.stories-C7IdnJd3.js → LinearProgress.stories-DcIpdz6R.js} +1 -1
- package/dist/storybook/assets/Pagination.stories-BBkLEwoP.js +252 -0
- package/dist/storybook/assets/{Popover.stories-Ca1F-wrI.js → Popover.stories-DLv48c2h.js} +1 -1
- package/dist/storybook/assets/{ReadyMixin-DNZ5dCsZ.js → ReadyMixin-Cw2Dfbu2.js} +1 -1
- package/dist/storybook/assets/RovingTabindexMixin.stories-BWaFx9mu.js +192 -0
- package/dist/storybook/assets/{Rtc.stories-BVJc1vCA.js → Rtc.stories-Ve7Bwo_l.js} +1 -1
- package/dist/storybook/assets/ScrollShadow.stories-C6XmrRLm.js +17 -0
- package/dist/storybook/assets/{Switch.stories-BEEHP8mD.js → Switch.stories-Cf8WM1LG.js} +1 -1
- package/dist/storybook/assets/Tab.stories-CEtdEtOx.js +218 -0
- package/dist/storybook/assets/Tabs.stories-CIAO1bPO.js +211 -0
- package/dist/storybook/assets/{Throttle.stories-C4xsYeAb.js → Throttle.stories-BqxVIb-r.js} +1 -1
- package/dist/storybook/assets/{Tooltip.stories-Ccm4AnSv.js → Tooltip.stories-B6fw6875.js} +1 -1
- package/dist/storybook/assets/{Welcome.stories-Degjk-M0.js → Welcome.stories-CfJtSM19.js} +1 -1
- package/dist/storybook/assets/{Widget.stories-OKnZ9sDs.js → Widget.stories-CiOho7lO.js} +1 -1
- package/dist/storybook/assets/{WithTooltip-65CFNBJE-CXL3TyJ2.js → WithTooltip-65CFNBJE-PGcopp73.js} +2 -2
- package/dist/storybook/assets/{blocks-DLdUKG_W.js → blocks-dP2DwISI.js} +5 -5
- package/dist/storybook/assets/{formatter-EIJCOSYU-29NCxjfM.js → formatter-EIJCOSYU-CZSAC3tg.js} +1 -1
- package/dist/storybook/assets/if-defined-B1RdczOE.js +1 -0
- package/dist/storybook/assets/{iframe-BqvwP3or.js → iframe-DloIUNZz.js} +161 -161
- package/dist/storybook/assets/iframe-bJgLXZKK.css +1 -0
- package/dist/storybook/assets/{index-BIyTv1BF.js → index-DKF0ypu5.js} +1 -1
- package/dist/storybook/assets/onFind-C0l4Gew0.js +1 -0
- package/dist/storybook/assets/{onFind.stories-D64-QZqf.js → onFind.stories-DOTt9puO.js} +1 -1
- package/dist/storybook/assets/{onRemove.stories-BICsnIJL.js → onRemove.stories-CQ9ZC5dm.js} +1 -1
- package/dist/storybook/assets/{onVisible.stories-DpDZP9_5.js → onVisible.stories-Cbj5_Vz0.js} +1 -1
- package/dist/storybook/assets/style-map-DLXysq3r.js +1 -0
- package/dist/storybook/assets/{syntaxhighlighter-ED5Y7EFY-Bz_DuQj8.js → syntaxhighlighter-ED5Y7EFY-Bjjbl9ca.js} +1 -1
- package/dist/storybook/iframe.html +2 -2
- package/dist/storybook/index.json +1 -1
- package/dist/storybook/project.json +1 -1
- package/dist/tailwind-plugin-action-bar.d.ts +2 -0
- package/dist/tailwind-plugin-action-bar.d.ts.map +1 -0
- package/dist/tailwind-plugin-action-bar.js +120 -0
- package/dist/tailwind-plugin-action-bar.js.map +1 -0
- package/dist/tailwind-plugin-action-bar.ts +134 -0
- package/dist/tailwind-plugin-badge.js +4 -5
- package/dist/tailwind-plugin-badge.js.map +1 -1
- package/dist/tailwind-plugin-badge.ts +4 -5
- package/dist/tailwind-plugin-button.js +1 -0
- package/dist/tailwind-plugin-button.js.map +1 -1
- package/dist/tailwind-plugin-button.ts +1 -0
- package/dist/tailwind-plugin-pagination.js +13 -23
- package/dist/tailwind-plugin-pagination.js.map +1 -1
- package/dist/tailwind-plugin-pagination.ts +15 -25
- package/dist/tailwind-plugin-tabs.d.ts +2 -0
- package/dist/tailwind-plugin-tabs.d.ts.map +1 -0
- package/dist/tailwind-plugin-tabs.js +151 -0
- package/dist/tailwind-plugin-tabs.js.map +1 -0
- package/dist/tailwind-plugin-tabs.ts +162 -0
- package/dist/util/EventEmitterMixin.d.ts +16 -0
- package/dist/util/EventEmitterMixin.d.ts.map +1 -1
- package/dist/util/EventEmitterMixin.js.map +1 -1
- package/dist/util/RovingTabindexMixin.d.ts +38 -0
- package/dist/util/RovingTabindexMixin.d.ts.map +1 -0
- package/dist/util/RovingTabindexMixin.js +83 -0
- package/dist/util/RovingTabindexMixin.js.map +1 -0
- package/docs/components/ActionBar.md +71 -0
- package/docs/components/ActionItem.md +76 -0
- package/docs/components/Dropdown.md +7 -7
- package/docs/components/DropdownItem.md +9 -5
- package/docs/components/DropdownMenu.md +12 -12
- package/docs/components/Pagination.md +37 -34
- package/docs/components/README.md +4 -0
- package/docs/components/Tab.md +73 -0
- package/docs/components/Tabs.md +77 -0
- package/package.json +1 -1
- package/dist/storybook/assets/Pagination.stories-C4cLjS_9.js +0 -272
- package/dist/storybook/assets/ScrollShadow.stories-C3W5o9ZW.js +0 -17
- package/dist/storybook/assets/if-defined-BZFPaJjl.js +0 -1
- package/dist/storybook/assets/iframe-C5bIZMJ5.css +0 -1
- package/dist/storybook/assets/onFind-1l3EPW-I.js +0 -1
- package/dist/storybook/assets/style-map-CBrSnxRe.js +0 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { LitElement, html, nothing } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { styleMap } from 'lit/directives/style-map.js';
|
|
10
|
+
import { EventEmitterMixin } from '../../util/EventEmitterMixin.js';
|
|
11
|
+
import { ReadyMixin } from '../../util/ReadyMixin.js';
|
|
12
|
+
import '../badge/Badge.js';
|
|
13
|
+
import '../icon/Icon.js';
|
|
14
|
+
/**
|
|
15
|
+
* An individual tab within a tab group.
|
|
16
|
+
*
|
|
17
|
+
* Renders a button with role="tab" that participates in keyboard navigation
|
|
18
|
+
* and selection state managed by the parent `btu-tabs` container.
|
|
19
|
+
*
|
|
20
|
+
* @element btu-tab
|
|
21
|
+
*
|
|
22
|
+
* @fires {CustomEvent} btu-tab-ready - Fired after first render
|
|
23
|
+
* @fires {CustomEvent<{name: string}>} btu-tab-change - Fired when a non-disabled tab with a name is clicked
|
|
24
|
+
*
|
|
25
|
+
* @cssprop --badge-color-background - Background color of the count indicator badge (default: gray-50)
|
|
26
|
+
* @cssprop --badge-color-foreground - Text color of the count indicator badge (default: gray-700)
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```html
|
|
30
|
+
* <btu-tabs>
|
|
31
|
+
* <btu-tab name="main" label="Main"></btu-tab>
|
|
32
|
+
* <btu-tab name="seo" label="SEO"></btu-tab>
|
|
33
|
+
* <btu-tab name="styles" label="Styles" disabled></btu-tab>
|
|
34
|
+
* </btu-tabs>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export default class Tab extends EventEmitterMixin(ReadyMixin(LitElement)) {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(...arguments);
|
|
40
|
+
/**
|
|
41
|
+
* Whether the tab is disabled and non-interactive.
|
|
42
|
+
* @attr
|
|
43
|
+
*/
|
|
44
|
+
this.disabled = false;
|
|
45
|
+
/**
|
|
46
|
+
* Placement of the icon relative to the label.
|
|
47
|
+
* @attr icon-position
|
|
48
|
+
*/
|
|
49
|
+
this.iconPosition = 'leading';
|
|
50
|
+
/**
|
|
51
|
+
* When true, hides the label visually while maintaining accessibility.
|
|
52
|
+
* @attr icon-only
|
|
53
|
+
*/
|
|
54
|
+
this.iconOnly = false;
|
|
55
|
+
/**
|
|
56
|
+
* When true, displays an error badge on the tab.
|
|
57
|
+
* @attr
|
|
58
|
+
*/
|
|
59
|
+
this.error = false;
|
|
60
|
+
/** @internal Active state set by parent btu-tabs */
|
|
61
|
+
this._active = false;
|
|
62
|
+
/** @internal Roving tabindex value set by parent btu-tabs */
|
|
63
|
+
this._tabindex = -1;
|
|
64
|
+
/** @internal Set by parent btu-tabs */
|
|
65
|
+
this.size = 'md';
|
|
66
|
+
/** @internal */
|
|
67
|
+
this.initialClasses = [];
|
|
68
|
+
}
|
|
69
|
+
static get tagName() {
|
|
70
|
+
return 'BTU-TAB';
|
|
71
|
+
}
|
|
72
|
+
connectedCallback() {
|
|
73
|
+
super.connectedCallback();
|
|
74
|
+
if (this.className) {
|
|
75
|
+
this.initialClasses = this.className.split(' ').filter(c => c.trim());
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
createRenderRoot() {
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
willUpdate() {
|
|
82
|
+
this.className = [...this.initialClasses, 'btu-tab'].filter(Boolean).join(' ');
|
|
83
|
+
}
|
|
84
|
+
firstUpdated() {
|
|
85
|
+
this.emit('btu-tab-ready');
|
|
86
|
+
}
|
|
87
|
+
/** @internal */
|
|
88
|
+
handleClick() {
|
|
89
|
+
if (this.disabled || !this.name)
|
|
90
|
+
return;
|
|
91
|
+
this.emit('btu-tab-change', { name: this.name });
|
|
92
|
+
}
|
|
93
|
+
render() {
|
|
94
|
+
const iconTemplate = this.iconName
|
|
95
|
+
? html `<btu-icon symbol="${this.iconName}" size="${this.size === 'lg' ? 'md' : 'sm'}"></btu-icon>`
|
|
96
|
+
: nothing;
|
|
97
|
+
const labelTemplate = this.iconOnly && this.iconName ? nothing : html `<span>${this.label}</span>`;
|
|
98
|
+
const badgeTemplate = this.badge != null ? html `<btu-badge size="sm">${this.badge}</btu-badge>` : nothing;
|
|
99
|
+
const errorDot = this.error ? html `<btu-badge size="sm" variant="error">!</btu-badge>` : nothing;
|
|
100
|
+
const indicator = this._active && !this.disabled
|
|
101
|
+
? html `<span
|
|
102
|
+
class="btu-tab-indicator"
|
|
103
|
+
style=${styleMap(this.error ? { background: 'oklch(var(--btu-theme-error-600))' } : {})}
|
|
104
|
+
></span>`
|
|
105
|
+
: nothing;
|
|
106
|
+
return html `<button
|
|
107
|
+
type="button"
|
|
108
|
+
role="tab"
|
|
109
|
+
class="btu-tab-button btu-tab-button-${this.size}"
|
|
110
|
+
aria-selected="${this._active}"
|
|
111
|
+
aria-disabled="${this.disabled || nothing}"
|
|
112
|
+
aria-description="${this.description || nothing}"
|
|
113
|
+
aria-label="${this.iconOnly && this.label ? this.label : nothing}"
|
|
114
|
+
tabindex="${this._tabindex}"
|
|
115
|
+
@click=${this.handleClick}
|
|
116
|
+
>
|
|
117
|
+
${this.iconPosition === 'leading' ? iconTemplate : nothing} ${labelTemplate}
|
|
118
|
+
${this.iconPosition === 'trailing' ? iconTemplate : nothing} ${badgeTemplate} ${errorDot} ${indicator}
|
|
119
|
+
</button>`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
__decorate([
|
|
123
|
+
property({ type: String, attribute: 'name', reflect: true })
|
|
124
|
+
], Tab.prototype, "name", void 0);
|
|
125
|
+
__decorate([
|
|
126
|
+
property({ type: String })
|
|
127
|
+
], Tab.prototype, "label", void 0);
|
|
128
|
+
__decorate([
|
|
129
|
+
property({ type: String })
|
|
130
|
+
], Tab.prototype, "description", void 0);
|
|
131
|
+
__decorate([
|
|
132
|
+
property({ type: Boolean, reflect: true })
|
|
133
|
+
], Tab.prototype, "disabled", void 0);
|
|
134
|
+
__decorate([
|
|
135
|
+
property({ type: String, attribute: 'icon-name' })
|
|
136
|
+
], Tab.prototype, "iconName", void 0);
|
|
137
|
+
__decorate([
|
|
138
|
+
property({ type: String, attribute: 'icon-position' })
|
|
139
|
+
], Tab.prototype, "iconPosition", void 0);
|
|
140
|
+
__decorate([
|
|
141
|
+
property({ type: Boolean, attribute: 'icon-only' })
|
|
142
|
+
], Tab.prototype, "iconOnly", void 0);
|
|
143
|
+
__decorate([
|
|
144
|
+
property({ type: Boolean, attribute: 'error' })
|
|
145
|
+
], Tab.prototype, "error", void 0);
|
|
146
|
+
__decorate([
|
|
147
|
+
property({ attribute: 'badge' })
|
|
148
|
+
], Tab.prototype, "badge", void 0);
|
|
149
|
+
if (!customElements.get('btu-tab')) {
|
|
150
|
+
customElements.define('btu-tab', Tab);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=Tab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tab.js","sourceRoot":"","sources":["../../../src/components/tabs/Tab.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import '../badge/Badge.js';
|
|
3
|
+
import '../dropdown/Dropdown.js';
|
|
4
|
+
import '../dropdown/DropdownItem.js';
|
|
5
|
+
import '../dropdown/DropdownMenu.js';
|
|
6
|
+
import '../icon/Icon.js';
|
|
7
|
+
export interface TabsProps {
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
9
|
+
activeTab?: string;
|
|
10
|
+
variant?: 'full' | 'menu';
|
|
11
|
+
}
|
|
12
|
+
declare const Tabs_base: (new (...args: any[]) => import("../../util/RovingTabindexMixin.js").RovingTabindexInterface) & (new (...args: any[]) => import("../../util/EventEmitterMixin.js").EventEmitterMixinInterface) & (new (...args: any[]) => import("../../util/ReadyMixin.js").ReadyMixinInterface) & typeof LitElement;
|
|
13
|
+
/**
|
|
14
|
+
* A container component for managing a group of tabs.
|
|
15
|
+
*
|
|
16
|
+
* Provides selection state management, size propagation to child tabs,
|
|
17
|
+
* and keyboard navigation following the WAI-ARIA Tabs pattern.
|
|
18
|
+
*
|
|
19
|
+
* When a tab becomes active, direct sibling elements that share the same
|
|
20
|
+
* `name` value are shown; other siblings with a `name` attribute are
|
|
21
|
+
* hidden. Only direct siblings are managed — nested tab groups control their
|
|
22
|
+
* own panels independently.
|
|
23
|
+
*
|
|
24
|
+
* @element btu-tabs
|
|
25
|
+
*
|
|
26
|
+
* @fires {CustomEvent} btu-tabs-ready - Fired after first render and initialization
|
|
27
|
+
* @fires {CustomEvent<{name: string}>} btu-tabs-show - Fired when a tab becomes active
|
|
28
|
+
* @fires {CustomEvent<{name: string}>} btu-tabs-hide - Fired when a tab is deactivated
|
|
29
|
+
* @fires {CustomEvent<{name: string}>} btu-tab-change - Fired when a tab is selected (bubbles from btu-tab)
|
|
30
|
+
* @fires {CustomEvent} btu-tab-ready - Fired when a child tab finishes initialization (bubbles from btu-tab)
|
|
31
|
+
*
|
|
32
|
+
* @cssprop --tabs-active-color - Text and icon color of the active tab (default: gray-700)
|
|
33
|
+
* @cssprop --tabs-active-indicator-color - Color of the active tab underline indicator (default: primary-500 → primary-700 → primary-900 gradient)
|
|
34
|
+
* @cssprop --tabs-border-color - Color of the bottom border divider (default: gray-200)
|
|
35
|
+
* @cssprop --tabs-color - Text and icon color for all tabs (default: gray-500; active/hover tabs use gray-700)
|
|
36
|
+
* @cssprop --tabs-background - Background color for all tab buttons (default: transparent)
|
|
37
|
+
* @cssprop --tabs-container-background - Background color of the tabs container (default: theme white)
|
|
38
|
+
* @cssprop --tabs-hover-background - Background color of a tab on hover (default: gray-100)
|
|
39
|
+
* @cssprop --tabs-hover-color - Text and icon color of a tab on hover (default: gray-700)
|
|
40
|
+
* @cssprop --tabs-gap - Spacing between tabs (default: 1rem)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```html
|
|
44
|
+
* <div>
|
|
45
|
+
* <btu-tabs size="md" active-tab="main">
|
|
46
|
+
* <btu-tab name="main" label="Main"></btu-tab>
|
|
47
|
+
* <btu-tab name="seo" label="SEO"></btu-tab>
|
|
48
|
+
* <btu-tab name="overrides" label="Overrides"></btu-tab>
|
|
49
|
+
* </btu-tabs>
|
|
50
|
+
* <div name="main" role="tabpanel">Main content</div>
|
|
51
|
+
* <div name="seo" role="tabpanel">SEO content</div>
|
|
52
|
+
* <div name="overrides" role="tabpanel">Overrides content</div>
|
|
53
|
+
* </div>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export default class Tabs extends Tabs_base {
|
|
57
|
+
static get tagName(): string;
|
|
58
|
+
/**
|
|
59
|
+
* Size variant applied to all child tabs.
|
|
60
|
+
* @attr
|
|
61
|
+
*/
|
|
62
|
+
size: 'xs' | 'sm' | 'md' | 'lg';
|
|
63
|
+
/**
|
|
64
|
+
* The `name` value of the currently active tab.
|
|
65
|
+
* @attr active-tab
|
|
66
|
+
*/
|
|
67
|
+
activeTab?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Layout variant.
|
|
70
|
+
* - 'full': tabs scroll horizontally when they overflow (default)
|
|
71
|
+
* - 'menu': all tabs are hidden; the active tab label and a chevron dropdown are shown instead
|
|
72
|
+
* @attr variant
|
|
73
|
+
*/
|
|
74
|
+
variant: 'full' | 'menu';
|
|
75
|
+
/** @internal */
|
|
76
|
+
private initialClasses;
|
|
77
|
+
/** @internal Bound event handler for cleanup */
|
|
78
|
+
private boundHandleTabChange;
|
|
79
|
+
/** @internal Bound event handler for cleanup */
|
|
80
|
+
private boundHandleKeyDown;
|
|
81
|
+
/** @internal */
|
|
82
|
+
_getRovingTargets(): HTMLElement[];
|
|
83
|
+
/** @internal Menu variant state */
|
|
84
|
+
private rafId;
|
|
85
|
+
private menuWrapper;
|
|
86
|
+
private menuDropdown;
|
|
87
|
+
private menuLabel;
|
|
88
|
+
private menuIcon;
|
|
89
|
+
private menuErrorBadge;
|
|
90
|
+
connectedCallback(): void;
|
|
91
|
+
disconnectedCallback(): void;
|
|
92
|
+
createRenderRoot(): this;
|
|
93
|
+
willUpdate(): void;
|
|
94
|
+
firstUpdated(): void;
|
|
95
|
+
updated(changedProperties: Map<string, unknown>): void;
|
|
96
|
+
/** @internal Tear down a variant's DOM and state before switching to another */
|
|
97
|
+
private teardownVariant;
|
|
98
|
+
/** @internal */
|
|
99
|
+
private syncTabs;
|
|
100
|
+
/** @internal Show/hide panel elements that are direct siblings with a matching name value */
|
|
101
|
+
private syncPanels;
|
|
102
|
+
/** @internal */
|
|
103
|
+
private getTabs;
|
|
104
|
+
/** @internal */
|
|
105
|
+
private activateTab;
|
|
106
|
+
/** @internal */
|
|
107
|
+
private handleTabChange;
|
|
108
|
+
/** @internal Keyboard navigation following WAI-ARIA Tabs pattern */
|
|
109
|
+
private handleKeyDown;
|
|
110
|
+
/** @internal */
|
|
111
|
+
private tabSizeToDropdownSize;
|
|
112
|
+
/** @internal */
|
|
113
|
+
private initMenu;
|
|
114
|
+
/** @internal */
|
|
115
|
+
private updateMenuItems;
|
|
116
|
+
/** @internal */
|
|
117
|
+
private syncMenuState;
|
|
118
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
119
|
+
}
|
|
120
|
+
declare global {
|
|
121
|
+
interface HTMLElementTagNameMap {
|
|
122
|
+
'btu-tabs': Tabs;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export {};
|
|
126
|
+
//# sourceMappingURL=Tabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/tabs/Tabs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,KAAK,CAAA;AAKtC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,yBAAyB,CAAA;AAEhC,OAAO,6BAA6B,CAAA;AAEpC,OAAO,6BAA6B,CAAA;AAEpC,OAAO,iBAAiB,CAAA;AAGxB,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC1B;;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,SAA8D;IAC9F,MAAM,KAAK,OAAO,WAEjB;IAED;;;OAGG;IAEH,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAO;IAEtC;;;OAGG;IAEH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;;OAKG;IAEH,OAAO,EAAE,MAAM,GAAG,MAAM,CAAS;IAEjC,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAAe;IAErC,gDAAgD;IAChD,OAAO,CAAC,oBAAoB,CAAkC;IAC9D,gDAAgD;IAChD,OAAO,CAAC,kBAAkB,CAAgC;IAE1D,gBAAgB;IAChB,iBAAiB,IAAI,WAAW,EAAE;IAUlC,mCAAmC;IACnC,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,YAAY,CAAwB;IAC5C,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,cAAc,CAA2B;IAEjD,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;IAU5B,gBAAgB;IAIhB,UAAU,IAAI,IAAI;IAWlB,YAAY,IAAI,IAAI;IAcpB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAoBtD,gFAAgF;IAChF,OAAO,CAAC,eAAe;IAYvB,gBAAgB;IAChB,OAAO,CAAC,QAAQ;IAYhB,6FAA6F;IAC7F,OAAO,CAAC,UAAU;IAWlB,gBAAgB;IAChB,OAAO,CAAC,OAAO;IAIf,gBAAgB;IAChB,OAAO,CAAC,WAAW;IAsBnB,gBAAgB;IAChB,OAAO,CAAC,eAAe;IAIvB,oEAAoE;IACpE,OAAO,CAAC,aAAa;IAuBrB,gBAAgB;IAChB,OAAO,CAAC,qBAAqB;IAM7B,gBAAgB;IAChB,OAAO,CAAC,QAAQ;IA+DhB,gBAAgB;IAChB,OAAO,CAAC,eAAe;IAsBvB,gBAAgB;IAChB,OAAO,CAAC,aAAa;IA4BrB,MAAM;CAGP;AAMD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,UAAU,EAAE,IAAI,CAAA;KACjB;CACF"}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { LitElement, html } from 'lit';
|
|
8
|
+
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { EventEmitterMixin } from '../../util/EventEmitterMixin.js';
|
|
10
|
+
import { ReadyMixin } from '../../util/ReadyMixin.js';
|
|
11
|
+
import { RovingTabindexMixin } from '../../util/RovingTabindexMixin.js';
|
|
12
|
+
import '../badge/Badge.js';
|
|
13
|
+
import '../dropdown/Dropdown.js';
|
|
14
|
+
import '../dropdown/DropdownItem.js';
|
|
15
|
+
import '../dropdown/DropdownMenu.js';
|
|
16
|
+
import '../icon/Icon.js';
|
|
17
|
+
/**
|
|
18
|
+
* A container component for managing a group of tabs.
|
|
19
|
+
*
|
|
20
|
+
* Provides selection state management, size propagation to child tabs,
|
|
21
|
+
* and keyboard navigation following the WAI-ARIA Tabs pattern.
|
|
22
|
+
*
|
|
23
|
+
* When a tab becomes active, direct sibling elements that share the same
|
|
24
|
+
* `name` value are shown; other siblings with a `name` attribute are
|
|
25
|
+
* hidden. Only direct siblings are managed — nested tab groups control their
|
|
26
|
+
* own panels independently.
|
|
27
|
+
*
|
|
28
|
+
* @element btu-tabs
|
|
29
|
+
*
|
|
30
|
+
* @fires {CustomEvent} btu-tabs-ready - Fired after first render and initialization
|
|
31
|
+
* @fires {CustomEvent<{name: string}>} btu-tabs-show - Fired when a tab becomes active
|
|
32
|
+
* @fires {CustomEvent<{name: string}>} btu-tabs-hide - Fired when a tab is deactivated
|
|
33
|
+
* @fires {CustomEvent<{name: string}>} btu-tab-change - Fired when a tab is selected (bubbles from btu-tab)
|
|
34
|
+
* @fires {CustomEvent} btu-tab-ready - Fired when a child tab finishes initialization (bubbles from btu-tab)
|
|
35
|
+
*
|
|
36
|
+
* @cssprop --tabs-active-color - Text and icon color of the active tab (default: gray-700)
|
|
37
|
+
* @cssprop --tabs-active-indicator-color - Color of the active tab underline indicator (default: primary-500 → primary-700 → primary-900 gradient)
|
|
38
|
+
* @cssprop --tabs-border-color - Color of the bottom border divider (default: gray-200)
|
|
39
|
+
* @cssprop --tabs-color - Text and icon color for all tabs (default: gray-500; active/hover tabs use gray-700)
|
|
40
|
+
* @cssprop --tabs-background - Background color for all tab buttons (default: transparent)
|
|
41
|
+
* @cssprop --tabs-container-background - Background color of the tabs container (default: theme white)
|
|
42
|
+
* @cssprop --tabs-hover-background - Background color of a tab on hover (default: gray-100)
|
|
43
|
+
* @cssprop --tabs-hover-color - Text and icon color of a tab on hover (default: gray-700)
|
|
44
|
+
* @cssprop --tabs-gap - Spacing between tabs (default: 1rem)
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```html
|
|
48
|
+
* <div>
|
|
49
|
+
* <btu-tabs size="md" active-tab="main">
|
|
50
|
+
* <btu-tab name="main" label="Main"></btu-tab>
|
|
51
|
+
* <btu-tab name="seo" label="SEO"></btu-tab>
|
|
52
|
+
* <btu-tab name="overrides" label="Overrides"></btu-tab>
|
|
53
|
+
* </btu-tabs>
|
|
54
|
+
* <div name="main" role="tabpanel">Main content</div>
|
|
55
|
+
* <div name="seo" role="tabpanel">SEO content</div>
|
|
56
|
+
* <div name="overrides" role="tabpanel">Overrides content</div>
|
|
57
|
+
* </div>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export default class Tabs extends RovingTabindexMixin(EventEmitterMixin(ReadyMixin(LitElement))) {
|
|
61
|
+
constructor() {
|
|
62
|
+
super(...arguments);
|
|
63
|
+
/**
|
|
64
|
+
* Size variant applied to all child tabs.
|
|
65
|
+
* @attr
|
|
66
|
+
*/
|
|
67
|
+
this.size = 'md';
|
|
68
|
+
/**
|
|
69
|
+
* Layout variant.
|
|
70
|
+
* - 'full': tabs scroll horizontally when they overflow (default)
|
|
71
|
+
* - 'menu': all tabs are hidden; the active tab label and a chevron dropdown are shown instead
|
|
72
|
+
* @attr variant
|
|
73
|
+
*/
|
|
74
|
+
this.variant = 'full';
|
|
75
|
+
/** @internal */
|
|
76
|
+
this.initialClasses = [];
|
|
77
|
+
/** @internal Bound event handler for cleanup */
|
|
78
|
+
this.boundHandleTabChange = this.handleTabChange.bind(this);
|
|
79
|
+
/** @internal Bound event handler for cleanup */
|
|
80
|
+
this.boundHandleKeyDown = this.handleKeyDown.bind(this);
|
|
81
|
+
/** @internal Menu variant state */
|
|
82
|
+
this.rafId = null;
|
|
83
|
+
this.menuWrapper = null;
|
|
84
|
+
this.menuDropdown = null;
|
|
85
|
+
this.menuLabel = null;
|
|
86
|
+
this.menuIcon = null;
|
|
87
|
+
this.menuErrorBadge = null;
|
|
88
|
+
}
|
|
89
|
+
static get tagName() {
|
|
90
|
+
return 'BTU-TABS';
|
|
91
|
+
}
|
|
92
|
+
/** @internal */
|
|
93
|
+
_getRovingTargets() {
|
|
94
|
+
const buttons = [];
|
|
95
|
+
for (const tab of this.getTabs()) {
|
|
96
|
+
if (tab.style.display === 'none')
|
|
97
|
+
continue;
|
|
98
|
+
const btn = tab.querySelector('button');
|
|
99
|
+
if (btn)
|
|
100
|
+
buttons.push(btn);
|
|
101
|
+
}
|
|
102
|
+
return buttons;
|
|
103
|
+
}
|
|
104
|
+
connectedCallback() {
|
|
105
|
+
super.connectedCallback();
|
|
106
|
+
if (this.className) {
|
|
107
|
+
this.initialClasses = this.className.split(' ').filter(c => c.trim());
|
|
108
|
+
}
|
|
109
|
+
this.setAttribute('role', 'tablist');
|
|
110
|
+
this.addEventListener('btu-tab-change', this.boundHandleTabChange);
|
|
111
|
+
this.addEventListener('keydown', this.boundHandleKeyDown);
|
|
112
|
+
}
|
|
113
|
+
disconnectedCallback() {
|
|
114
|
+
super.disconnectedCallback();
|
|
115
|
+
if (this.rafId) {
|
|
116
|
+
cancelAnimationFrame(this.rafId);
|
|
117
|
+
this.rafId = null;
|
|
118
|
+
}
|
|
119
|
+
this.removeEventListener('btu-tab-change', this.boundHandleTabChange);
|
|
120
|
+
this.removeEventListener('keydown', this.boundHandleKeyDown);
|
|
121
|
+
}
|
|
122
|
+
createRenderRoot() {
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
willUpdate() {
|
|
126
|
+
this.className = [
|
|
127
|
+
...this.initialClasses,
|
|
128
|
+
'btu-tabs',
|
|
129
|
+
`btu-tabs-${this.size}`,
|
|
130
|
+
this.variant === 'menu' ? 'btu-tabs-menu-mode' : '',
|
|
131
|
+
]
|
|
132
|
+
.filter(Boolean)
|
|
133
|
+
.join(' ');
|
|
134
|
+
}
|
|
135
|
+
firstUpdated() {
|
|
136
|
+
if (!this.activeTab) {
|
|
137
|
+
const firstEnabled = this.getTabs().find(t => !t.disabled);
|
|
138
|
+
if (firstEnabled)
|
|
139
|
+
this.activeTab = firstEnabled.name;
|
|
140
|
+
}
|
|
141
|
+
this.syncTabs();
|
|
142
|
+
this.syncPanels();
|
|
143
|
+
if (this.variant === 'menu') {
|
|
144
|
+
this.initMenu();
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.emit('btu-tabs-ready');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
updated(changedProperties) {
|
|
151
|
+
if (changedProperties.has('activeTab') && !this.activeTab) {
|
|
152
|
+
const firstEnabled = this.getTabs().find(t => !t.disabled);
|
|
153
|
+
if (firstEnabled)
|
|
154
|
+
this.activeTab = firstEnabled.name;
|
|
155
|
+
}
|
|
156
|
+
if (changedProperties.has('activeTab') || changedProperties.has('size')) {
|
|
157
|
+
this.syncTabs();
|
|
158
|
+
}
|
|
159
|
+
if (changedProperties.has('activeTab')) {
|
|
160
|
+
this.syncPanels();
|
|
161
|
+
}
|
|
162
|
+
if (changedProperties.has('size') && this.menuDropdown) {
|
|
163
|
+
this.menuDropdown.size = this.tabSizeToDropdownSize(this.size);
|
|
164
|
+
}
|
|
165
|
+
if (changedProperties.has('variant') && changedProperties.get('variant') !== undefined) {
|
|
166
|
+
this.teardownVariant(changedProperties.get('variant'));
|
|
167
|
+
if (this.variant === 'menu')
|
|
168
|
+
this.initMenu();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** @internal Tear down a variant's DOM and state before switching to another */
|
|
172
|
+
teardownVariant(previous) {
|
|
173
|
+
if (previous === 'menu') {
|
|
174
|
+
this.menuWrapper?.remove();
|
|
175
|
+
this.menuWrapper = null;
|
|
176
|
+
this.menuDropdown = null;
|
|
177
|
+
this.menuLabel = null;
|
|
178
|
+
this.menuIcon = null;
|
|
179
|
+
this.menuErrorBadge = null;
|
|
180
|
+
this.getTabs().forEach(tab => tab.style.removeProperty('display'));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** @internal */
|
|
184
|
+
syncTabs() {
|
|
185
|
+
this.getTabs().forEach(tab => {
|
|
186
|
+
tab.size = this.size;
|
|
187
|
+
tab._active = tab.name === this.activeTab;
|
|
188
|
+
tab._tabindex = tab.name === this.activeTab ? 0 : -1;
|
|
189
|
+
tab.requestUpdate();
|
|
190
|
+
});
|
|
191
|
+
if (this.variant === 'menu') {
|
|
192
|
+
this.syncMenuState();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** @internal Show/hide panel elements that are direct siblings with a matching name value */
|
|
196
|
+
syncPanels() {
|
|
197
|
+
if (!this.activeTab || !this.parentElement)
|
|
198
|
+
return;
|
|
199
|
+
Array.from(this.parentElement.children).forEach(child => {
|
|
200
|
+
if (child === this || !(child instanceof HTMLElement))
|
|
201
|
+
return;
|
|
202
|
+
// data-tab is a deprecated fallback for compat — use name instead
|
|
203
|
+
const panelName = child.getAttribute('name') ?? child.dataset.tab;
|
|
204
|
+
if (!panelName)
|
|
205
|
+
return;
|
|
206
|
+
child.hidden = panelName !== this.activeTab;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/** @internal */
|
|
210
|
+
getTabs() {
|
|
211
|
+
return Array.from(this.querySelectorAll('btu-tab'));
|
|
212
|
+
}
|
|
213
|
+
/** @internal */
|
|
214
|
+
activateTab(name) {
|
|
215
|
+
const newTab = this.getTabs().find(t => t.name === name);
|
|
216
|
+
if (!newTab || newTab.disabled) {
|
|
217
|
+
const available = this.getTabs()
|
|
218
|
+
.map(t => t.name)
|
|
219
|
+
.filter(Boolean);
|
|
220
|
+
console.warn(`[btu-tabs] Tab "${name}" not found or is disabled. Available tabs: ${available.join(', ')}`);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (name === this.activeTab)
|
|
224
|
+
return;
|
|
225
|
+
const oldName = this.activeTab;
|
|
226
|
+
if (oldName) {
|
|
227
|
+
this.emit('btu-tabs-hide', { name: oldName });
|
|
228
|
+
}
|
|
229
|
+
this.activeTab = name;
|
|
230
|
+
this.emit('btu-tabs-show', { name });
|
|
231
|
+
this.syncTabs();
|
|
232
|
+
this.syncPanels();
|
|
233
|
+
}
|
|
234
|
+
/** @internal */
|
|
235
|
+
handleTabChange(event) {
|
|
236
|
+
this.activateTab(event.detail.name);
|
|
237
|
+
}
|
|
238
|
+
/** @internal Keyboard navigation following WAI-ARIA Tabs pattern */
|
|
239
|
+
handleKeyDown(event) {
|
|
240
|
+
switch (event.key) {
|
|
241
|
+
case 'ArrowRight':
|
|
242
|
+
event.preventDefault();
|
|
243
|
+
this._rovingNext();
|
|
244
|
+
break;
|
|
245
|
+
case 'ArrowLeft':
|
|
246
|
+
event.preventDefault();
|
|
247
|
+
this._rovingPrev();
|
|
248
|
+
break;
|
|
249
|
+
case 'Home':
|
|
250
|
+
event.preventDefault();
|
|
251
|
+
this._rovingFirst();
|
|
252
|
+
break;
|
|
253
|
+
case 'End':
|
|
254
|
+
event.preventDefault();
|
|
255
|
+
this._rovingLast();
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// ─── Menu variant ────────────────────────────────────────────────────────────
|
|
260
|
+
/** @internal */
|
|
261
|
+
tabSizeToDropdownSize(size) {
|
|
262
|
+
if (size === 'xs' || size === 'sm')
|
|
263
|
+
return 'small';
|
|
264
|
+
if (size === 'lg')
|
|
265
|
+
return 'large';
|
|
266
|
+
return 'medium';
|
|
267
|
+
}
|
|
268
|
+
/** @internal */
|
|
269
|
+
initMenu() {
|
|
270
|
+
// Hide all tab buttons — they're only accessible via the dropdown
|
|
271
|
+
this.getTabs().forEach(tab => (tab.style.display = 'none'));
|
|
272
|
+
const activeTab = this.getTabs().find(t => t.name === this.activeTab);
|
|
273
|
+
this.menuWrapper = document.createElement('div');
|
|
274
|
+
const wrapper = this.menuWrapper;
|
|
275
|
+
wrapper.className = 'btu-tab-menu-wrapper';
|
|
276
|
+
this.menuIcon = document.createElement('btu-icon');
|
|
277
|
+
this.menuIcon.setAttribute('size', this.size === 'lg' ? 'md' : 'sm');
|
|
278
|
+
this.menuIcon.setAttribute('symbol', activeTab?.iconName ?? '');
|
|
279
|
+
this.menuIcon.hidden = !activeTab?.iconName;
|
|
280
|
+
this.menuLabel = document.createElement('span');
|
|
281
|
+
this.menuLabel.className = 'btu-tab-menu-label';
|
|
282
|
+
this.menuLabel.textContent = activeTab?.label ?? '';
|
|
283
|
+
if (activeTab?.iconPosition === 'trailing') {
|
|
284
|
+
wrapper.appendChild(this.menuLabel);
|
|
285
|
+
wrapper.appendChild(this.menuIcon);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
wrapper.appendChild(this.menuIcon);
|
|
289
|
+
wrapper.appendChild(this.menuLabel);
|
|
290
|
+
}
|
|
291
|
+
this.menuErrorBadge = document.createElement('btu-badge');
|
|
292
|
+
this.menuErrorBadge.setAttribute('size', 'sm');
|
|
293
|
+
this.menuErrorBadge.setAttribute('variant', 'error');
|
|
294
|
+
this.menuErrorBadge.textContent = '!';
|
|
295
|
+
this.menuErrorBadge.hidden = !activeTab?.error;
|
|
296
|
+
wrapper.appendChild(this.menuErrorBadge);
|
|
297
|
+
const dropdownMenu = document.createElement('btu-dropdown-menu');
|
|
298
|
+
this.menuDropdown = document.createElement('btu-dropdown');
|
|
299
|
+
this.menuDropdown.label = 'Tabs';
|
|
300
|
+
this.menuDropdown.iconOnly = true;
|
|
301
|
+
this.menuDropdown.noChevron = false;
|
|
302
|
+
this.menuDropdown.variant = 'tertiary';
|
|
303
|
+
this.menuDropdown.placement = 'bottom-start';
|
|
304
|
+
this.menuDropdown.size = this.tabSizeToDropdownSize(this.size);
|
|
305
|
+
this.menuDropdown.appendChild(dropdownMenu);
|
|
306
|
+
this.menuDropdown.addEventListener('btu-dropdown-item-select', (e) => {
|
|
307
|
+
e.stopPropagation();
|
|
308
|
+
const item = e.target.closest('btu-dropdown-item');
|
|
309
|
+
const name = item?.dataset.name;
|
|
310
|
+
if (name)
|
|
311
|
+
this.activateTab(name);
|
|
312
|
+
});
|
|
313
|
+
wrapper.appendChild(this.menuDropdown);
|
|
314
|
+
this.appendChild(wrapper);
|
|
315
|
+
// Defer population to allow btu-dropdown to finish its firstUpdated lifecycle
|
|
316
|
+
this.rafId = requestAnimationFrame(() => {
|
|
317
|
+
this.rafId = null;
|
|
318
|
+
this.updateMenuItems();
|
|
319
|
+
this.emit('btu-tabs-ready');
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
/** @internal */
|
|
323
|
+
updateMenuItems() {
|
|
324
|
+
if (!this.isConnected)
|
|
325
|
+
return;
|
|
326
|
+
const menu = this.menuDropdown?.querySelector('btu-dropdown-menu');
|
|
327
|
+
if (!menu)
|
|
328
|
+
return;
|
|
329
|
+
menu.innerHTML = '';
|
|
330
|
+
const tabs = this.getTabs();
|
|
331
|
+
const hasIcons = tabs.some(t => !!t.iconName);
|
|
332
|
+
tabs.forEach(tab => {
|
|
333
|
+
const item = document.createElement('btu-dropdown-item');
|
|
334
|
+
item.dataset.name = tab.name ?? '';
|
|
335
|
+
item.label = tab.label ?? tab.name ?? '';
|
|
336
|
+
item.selected = tab.name === this.activeTab;
|
|
337
|
+
item.disabled = tab.disabled;
|
|
338
|
+
item.error = tab.error;
|
|
339
|
+
if (tab.iconName)
|
|
340
|
+
item.iconSymbol = tab.iconName;
|
|
341
|
+
menu.appendChild(item);
|
|
342
|
+
item._configure({ checkbox: false, icon: hasIcons, iconSymbol: '', favorites: false, shortcuts: false });
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/** @internal */
|
|
346
|
+
syncMenuState() {
|
|
347
|
+
const activeTab = this.getTabs().find(t => t.name === this.activeTab);
|
|
348
|
+
if (this.menuLabel) {
|
|
349
|
+
this.menuLabel.textContent = activeTab?.label ?? '';
|
|
350
|
+
}
|
|
351
|
+
if (this.menuIcon) {
|
|
352
|
+
const symbol = activeTab?.iconName ?? '';
|
|
353
|
+
this.menuIcon.setAttribute('symbol', symbol);
|
|
354
|
+
this.menuIcon.setAttribute('size', this.size === 'lg' ? 'md' : 'sm');
|
|
355
|
+
this.menuIcon.hidden = !symbol;
|
|
356
|
+
// Reposition if icon-position changed
|
|
357
|
+
const wrapper = this.menuIcon.parentElement;
|
|
358
|
+
if (wrapper && this.menuLabel) {
|
|
359
|
+
if (activeTab?.iconPosition === 'trailing') {
|
|
360
|
+
wrapper.insertBefore(this.menuIcon, this.menuErrorBadge);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
wrapper.insertBefore(this.menuIcon, this.menuLabel);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (this.menuErrorBadge) {
|
|
368
|
+
this.menuErrorBadge.hidden = !activeTab?.error;
|
|
369
|
+
}
|
|
370
|
+
this.menuDropdown?.querySelectorAll('btu-dropdown-item').forEach(item => {
|
|
371
|
+
item.selected = item.dataset.name === this.activeTab;
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
render() {
|
|
375
|
+
return html ``;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
__decorate([
|
|
379
|
+
property({ type: String })
|
|
380
|
+
], Tabs.prototype, "size", void 0);
|
|
381
|
+
__decorate([
|
|
382
|
+
property({ type: String, attribute: 'active-tab' })
|
|
383
|
+
], Tabs.prototype, "activeTab", void 0);
|
|
384
|
+
__decorate([
|
|
385
|
+
property({ type: String })
|
|
386
|
+
], Tabs.prototype, "variant", void 0);
|
|
387
|
+
if (!customElements.get('btu-tabs')) {
|
|
388
|
+
customElements.define('btu-tabs', Tabs);
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=Tabs.js.map
|