@helixui/library 1.0.0 → 1.0.1
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/custom-elements.json +213 -22
- package/dist/components/hx-accordion/hx-accordion-item.d.ts +20 -0
- package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
- package/dist/components/hx-accordion/index.js +1 -1
- package/dist/components/hx-alert/hx-alert.d.ts +10 -0
- package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
- package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
- package/dist/components/hx-alert/index.js +1 -1
- package/dist/components/hx-badge/hx-badge.d.ts +2 -0
- package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
- package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
- package/dist/components/hx-badge/index.js +1 -1
- package/dist/components/hx-banner/hx-banner.d.ts +6 -0
- package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
- package/dist/components/hx-banner/index.js +1 -1
- package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
- package/dist/components/hx-breadcrumb/index.js +1 -1
- package/dist/components/hx-card/hx-card.d.ts +1 -0
- package/dist/components/hx-card/hx-card.d.ts.map +1 -1
- package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
- package/dist/components/hx-card/index.js +1 -1
- package/dist/components/hx-carousel/hx-carousel.styles.d.ts.map +1 -1
- package/dist/components/hx-carousel/index.js +1 -1
- package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
- package/dist/components/hx-checkbox/index.js +1 -1
- package/dist/components/hx-code-snippet/index.js +1 -1
- package/dist/components/hx-color-picker/hx-color-picker.d.ts +44 -10
- package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
- package/dist/components/hx-color-picker/index.js +1 -1
- package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
- package/dist/components/hx-combobox/index.js +1 -1
- package/dist/components/hx-data-table/hx-data-table.styles.d.ts.map +1 -1
- package/dist/components/hx-data-table/index.js +1 -1
- package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
- package/dist/components/hx-date-picker/index.js +1 -1
- package/dist/components/hx-dialog/hx-dialog.styles.d.ts.map +1 -1
- package/dist/components/hx-dialog/index.js +1 -1
- package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
- package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
- package/dist/components/hx-drawer/index.js +1 -1
- package/dist/components/hx-dropdown/hx-dropdown.d.ts +20 -5
- package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
- package/dist/components/hx-dropdown/index.js +1 -1
- package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
- package/dist/components/hx-file-upload/index.js +1 -1
- package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
- package/dist/components/hx-icon-button/index.js +1 -1
- package/dist/components/hx-menu/hx-menu-item.d.ts +1 -0
- package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
- package/dist/components/hx-menu/hx-menu.d.ts +1 -0
- package/dist/components/hx-menu/hx-menu.d.ts.map +1 -1
- package/dist/components/hx-menu/index.js +1 -1
- package/dist/components/hx-meter/hx-meter.d.ts +1 -0
- package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
- package/dist/components/hx-meter/hx-meter.styles.d.ts.map +1 -1
- package/dist/components/hx-meter/index.js +1 -1
- package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
- package/dist/components/hx-nav/index.js +1 -1
- package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
- package/dist/components/hx-overflow-menu/index.js +1 -1
- package/dist/components/hx-pagination/hx-pagination.styles.d.ts.map +1 -1
- package/dist/components/hx-pagination/index.js +1 -1
- package/dist/components/hx-popover/hx-popover.d.ts +41 -9
- package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
- package/dist/components/hx-popover/hx-popover.styles.d.ts.map +1 -1
- package/dist/components/hx-popover/index.js +1 -1
- package/dist/components/hx-progress-bar/hx-progress-bar.d.ts +2 -0
- package/dist/components/hx-progress-bar/hx-progress-bar.d.ts.map +1 -1
- package/dist/components/hx-progress-bar/index.js +1 -1
- package/dist/components/hx-radio-group/hx-radio.styles.d.ts.map +1 -1
- package/dist/components/hx-radio-group/index.js +1 -1
- package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
- package/dist/components/hx-select/index.js +1 -1
- package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
- package/dist/components/hx-slider/index.js +1 -1
- package/dist/components/hx-split-button/index.js +1 -1
- package/dist/components/hx-split-panel/hx-split-panel.d.ts +44 -11
- package/dist/components/hx-split-panel/hx-split-panel.d.ts.map +1 -1
- package/dist/components/hx-split-panel/hx-split-panel.styles.d.ts.map +1 -1
- package/dist/components/hx-split-panel/index.js +1 -1
- package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
- package/dist/components/hx-tabs/index.js +1 -1
- package/dist/components/hx-tag/hx-tag.d.ts +2 -0
- package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
- package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
- package/dist/components/hx-tag/index.js +1 -1
- package/dist/components/hx-text-input/hx-text-input.d.ts +1 -1
- package/dist/components/hx-text-input/index.js +1 -1
- package/dist/components/hx-time-picker/hx-time-picker.d.ts +80 -19
- package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
- package/dist/components/hx-time-picker/index.js +1 -1
- package/dist/components/hx-toast/hx-toast.d.ts +10 -0
- package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
- package/dist/components/hx-toast/hx-toast.styles.d.ts.map +1 -1
- package/dist/components/hx-toast/index.js +1 -1
- package/dist/components/hx-top-nav/index.js +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.d.ts +11 -1
- package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
- package/dist/components/hx-tree-view/hx-tree-view.d.ts +1 -0
- package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
- package/dist/components/hx-tree-view/index.js +1 -1
- package/dist/index.js +37 -37
- package/dist/shared/{hx-accordion-Cyswa6J3.js → hx-accordion-DT8qHOay.js} +54 -37
- package/dist/shared/hx-accordion-DT8qHOay.js.map +1 -0
- package/dist/shared/{hx-alert-Cg-zxRiU.js → hx-alert-D6uok29t.js} +95 -28
- package/dist/shared/hx-alert-D6uok29t.js.map +1 -0
- package/dist/shared/{hx-badge-CjT0d8NK.js → hx-badge-BeuWuUj_.js} +57 -31
- package/dist/shared/hx-badge-BeuWuUj_.js.map +1 -0
- package/dist/shared/{hx-banner-lxAIJ2kR.js → hx-banner-DnCBJtRR.js} +27 -23
- package/dist/shared/{hx-banner-lxAIJ2kR.js.map → hx-banner-DnCBJtRR.js.map} +1 -1
- package/dist/shared/{hx-breadcrumb-item-C0rz0fzV.js → hx-breadcrumb-item-Bj2UqhzR.js} +12 -8
- package/dist/shared/{hx-breadcrumb-item-C0rz0fzV.js.map → hx-breadcrumb-item-Bj2UqhzR.js.map} +1 -1
- package/dist/shared/{hx-card-Bg4W4uXC.js → hx-card-B9j2SHyI.js} +15 -11
- package/dist/shared/hx-card-B9j2SHyI.js.map +1 -0
- package/dist/shared/{hx-carousel-item-BKpmFbUT.js → hx-carousel-item-Be0bC-7o.js} +91 -77
- package/dist/shared/hx-carousel-item-Be0bC-7o.js.map +1 -0
- package/dist/shared/{hx-checkbox-BMayOpAM.js → hx-checkbox-CuaJqEo7.js} +3 -1
- package/dist/shared/hx-checkbox-CuaJqEo7.js.map +1 -0
- package/dist/shared/{hx-code-snippet-B4hV7rWG.js → hx-code-snippet-DBwIjl5p.js} +11 -11
- package/dist/shared/{hx-code-snippet-B4hV7rWG.js.map → hx-code-snippet-DBwIjl5p.js.map} +1 -1
- package/dist/shared/{hx-color-picker-BvfJ_h16.js → hx-color-picker-Bb2UPVc3.js} +2 -2
- package/dist/shared/hx-color-picker-Bb2UPVc3.js.map +1 -0
- package/dist/shared/{hx-combobox-BBi3izKJ.js → hx-combobox-CNvY-es8.js} +42 -39
- package/dist/shared/hx-combobox-CNvY-es8.js.map +1 -0
- package/dist/shared/{hx-data-table-DNiDVWR2.js → hx-data-table-BwoJCFgs.js} +9 -8
- package/dist/shared/hx-data-table-BwoJCFgs.js.map +1 -0
- package/dist/shared/{hx-date-picker-D7yCK0nk.js → hx-date-picker-DDcIBJir.js} +43 -37
- package/dist/shared/hx-date-picker-DDcIBJir.js.map +1 -0
- package/dist/shared/{hx-dialog-Z7Ou_AZ9.js → hx-dialog-M7so0sRT.js} +41 -34
- package/dist/shared/hx-dialog-M7so0sRT.js.map +1 -0
- package/dist/shared/{hx-drawer-Dk-_xzy0.js → hx-drawer-CYxuhIQ0.js} +50 -43
- package/dist/shared/hx-drawer-CYxuhIQ0.js.map +1 -0
- package/dist/shared/{hx-dropdown-DnjLnkTj.js → hx-dropdown-7cfowTWv.js} +30 -30
- package/dist/shared/hx-dropdown-7cfowTWv.js.map +1 -0
- package/dist/shared/{hx-file-upload-CUORgnKc.js → hx-file-upload-9HbONfqt.js} +49 -43
- package/dist/shared/hx-file-upload-9HbONfqt.js.map +1 -0
- package/dist/shared/{hx-icon-button-C83bCR0K.js → hx-icon-button-iu0i_faq.js} +39 -29
- package/dist/shared/hx-icon-button-iu0i_faq.js.map +1 -0
- package/dist/shared/{hx-menu-divider-11Dp2VfM.js → hx-menu-divider-DR8klkFT.js} +32 -26
- package/dist/shared/hx-menu-divider-DR8klkFT.js.map +1 -0
- package/dist/shared/{hx-meter-UinDQjl6.js → hx-meter-CZ7lnMra.js} +67 -35
- package/dist/shared/hx-meter-CZ7lnMra.js.map +1 -0
- package/dist/shared/{hx-nav-DSpwWYUX.js → hx-nav-DM6-cGKF.js} +49 -47
- package/dist/shared/hx-nav-DM6-cGKF.js.map +1 -0
- package/dist/shared/{hx-overflow-menu-C7k5wlZy.js → hx-overflow-menu-CobkjAb8.js} +17 -9
- package/dist/shared/{hx-overflow-menu-C7k5wlZy.js.map → hx-overflow-menu-CobkjAb8.js.map} +1 -1
- package/dist/shared/{hx-pagination-BQ0cLTuB.js → hx-pagination-10dpXS95.js} +14 -12
- package/dist/shared/hx-pagination-10dpXS95.js.map +1 -0
- package/dist/shared/hx-popover-ULjonbaO.js +269 -0
- package/dist/shared/hx-popover-ULjonbaO.js.map +1 -0
- package/dist/shared/{hx-progress-bar-C_mdPVF-.js → hx-progress-bar-CnTibV63.js} +67 -57
- package/dist/shared/{hx-progress-bar-C_mdPVF-.js.map → hx-progress-bar-CnTibV63.js.map} +1 -1
- package/dist/shared/{hx-radio-Bqyi8re3.js → hx-radio-BnKcRuQu.js} +10 -8
- package/dist/shared/{hx-radio-Bqyi8re3.js.map → hx-radio-BnKcRuQu.js.map} +1 -1
- package/dist/shared/{hx-select-BBae2LqN.js → hx-select-C50lD7NS.js} +4 -3
- package/dist/shared/hx-select-C50lD7NS.js.map +1 -0
- package/dist/shared/{hx-slider-CpnxH2UP.js → hx-slider-CprSNrRi.js} +3 -2
- package/dist/shared/hx-slider-CprSNrRi.js.map +1 -0
- package/dist/shared/{hx-split-button-BvwoG8h2.js → hx-split-button-CHGy4FUc.js} +11 -11
- package/dist/shared/{hx-split-button-BvwoG8h2.js.map → hx-split-button-CHGy4FUc.js.map} +1 -1
- package/dist/shared/{hx-split-panel-Cxkeauwe.js → hx-split-panel-DYtB45Tr.js} +16 -8
- package/dist/shared/hx-split-panel-DYtB45Tr.js.map +1 -0
- package/dist/shared/{hx-tab-panel-CHB0u1zF.js → hx-tab-panel-BRNcLICw.js} +55 -52
- package/dist/shared/hx-tab-panel-BRNcLICw.js.map +1 -0
- package/dist/shared/{hx-tag-SJJtMlOS.js → hx-tag-B3N-vZ6B.js} +80 -55
- package/dist/shared/hx-tag-B3N-vZ6B.js.map +1 -0
- package/dist/shared/{hx-text-input-BrCjo4fJ.js → hx-text-input-CCZZbWQ9.js} +6 -6
- package/dist/shared/hx-text-input-CCZZbWQ9.js.map +1 -0
- package/dist/shared/{hx-time-picker-DRRAFuVd.js → hx-time-picker-CJcIjH3C.js} +5 -2
- package/dist/shared/hx-time-picker-CJcIjH3C.js.map +1 -0
- package/dist/shared/{hx-top-nav-DzW7XLv-.js → hx-top-nav-D2bQpns3.js} +2 -2
- package/dist/shared/{hx-top-nav-DzW7XLv-.js.map → hx-top-nav-D2bQpns3.js.map} +1 -1
- package/dist/shared/{hx-tree-item-DdH6RbMs.js → hx-tree-item-BobGN76x.js} +119 -96
- package/dist/shared/hx-tree-item-BobGN76x.js.map +1 -0
- package/dist/shared/{toast-factory-B8jicczW.js → toast-factory-MvMMreTu.js} +178 -94
- package/dist/shared/toast-factory-MvMMreTu.js.map +1 -0
- package/package.json +1 -1
- package/dist/shared/hx-accordion-Cyswa6J3.js.map +0 -1
- package/dist/shared/hx-alert-Cg-zxRiU.js.map +0 -1
- package/dist/shared/hx-badge-CjT0d8NK.js.map +0 -1
- package/dist/shared/hx-card-Bg4W4uXC.js.map +0 -1
- package/dist/shared/hx-carousel-item-BKpmFbUT.js.map +0 -1
- package/dist/shared/hx-checkbox-BMayOpAM.js.map +0 -1
- package/dist/shared/hx-color-picker-BvfJ_h16.js.map +0 -1
- package/dist/shared/hx-combobox-BBi3izKJ.js.map +0 -1
- package/dist/shared/hx-data-table-DNiDVWR2.js.map +0 -1
- package/dist/shared/hx-date-picker-D7yCK0nk.js.map +0 -1
- package/dist/shared/hx-dialog-Z7Ou_AZ9.js.map +0 -1
- package/dist/shared/hx-drawer-Dk-_xzy0.js.map +0 -1
- package/dist/shared/hx-dropdown-DnjLnkTj.js.map +0 -1
- package/dist/shared/hx-file-upload-CUORgnKc.js.map +0 -1
- package/dist/shared/hx-icon-button-C83bCR0K.js.map +0 -1
- package/dist/shared/hx-menu-divider-11Dp2VfM.js.map +0 -1
- package/dist/shared/hx-meter-UinDQjl6.js.map +0 -1
- package/dist/shared/hx-nav-DSpwWYUX.js.map +0 -1
- package/dist/shared/hx-pagination-BQ0cLTuB.js.map +0 -1
- package/dist/shared/hx-popover-BQsgrJCW.js +0 -226
- package/dist/shared/hx-popover-BQsgrJCW.js.map +0 -1
- package/dist/shared/hx-select-BBae2LqN.js.map +0 -1
- package/dist/shared/hx-slider-CpnxH2UP.js.map +0 -1
- package/dist/shared/hx-split-panel-Cxkeauwe.js.map +0 -1
- package/dist/shared/hx-tab-panel-CHB0u1zF.js.map +0 -1
- package/dist/shared/hx-tag-SJJtMlOS.js.map +0 -1
- package/dist/shared/hx-text-input-BrCjo4fJ.js.map +0 -1
- package/dist/shared/hx-time-picker-DRRAFuVd.js.map +0 -1
- package/dist/shared/hx-tree-item-DdH6RbMs.js.map +0 -1
- package/dist/shared/toast-factory-B8jicczW.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { css as
|
|
2
|
-
import { query as
|
|
1
|
+
import { css as v, LitElement as x, nothing as d, html as c } from "lit";
|
|
2
|
+
import { query as m, state as g, property as u, customElement as f } from "lit/decorators.js";
|
|
3
3
|
import { classMap as h } from "lit/directives/class-map.js";
|
|
4
4
|
import { tokenStyles as _ } from "@helixui/tokens/lit";
|
|
5
|
-
const y =
|
|
5
|
+
const y = v`
|
|
6
6
|
:host {
|
|
7
7
|
display: inline-block;
|
|
8
8
|
position: relative;
|
|
@@ -311,7 +311,7 @@ var w = Object.defineProperty, k = Object.getOwnPropertyDescriptor, n = (t, r, e
|
|
|
311
311
|
(l = t[a]) && (o = (s ? l(r, e, o) : l(o)) || o);
|
|
312
312
|
return s && o && w(r, e, o), o;
|
|
313
313
|
};
|
|
314
|
-
let M = 0, i = class extends
|
|
314
|
+
let M = 0, i = class extends x {
|
|
315
315
|
constructor() {
|
|
316
316
|
super(...arguments), this._open = !1, this.variant = "primary", this.size = "md", this.disabled = !1, this.label = void 0, this.triggerLabel = "More actions", this.menuLabel = "Secondary actions", this._menuId = `hx-split-button-menu-${++M}`, this._handleOutsideClick = (t) => {
|
|
317
317
|
if (!this._open) return;
|
|
@@ -443,7 +443,7 @@ let M = 0, i = class extends v {
|
|
|
443
443
|
"split-button__chevron": !0,
|
|
444
444
|
"split-button__chevron--open": this._open
|
|
445
445
|
};
|
|
446
|
-
return
|
|
446
|
+
return c`
|
|
447
447
|
<div class=${h(t)}>
|
|
448
448
|
<!-- Primary action button -->
|
|
449
449
|
<button
|
|
@@ -451,11 +451,11 @@ let M = 0, i = class extends v {
|
|
|
451
451
|
class="split-button__primary"
|
|
452
452
|
?disabled=${this.disabled}
|
|
453
453
|
type="button"
|
|
454
|
-
aria-label=${this.ariaLabel ?? this.label
|
|
454
|
+
aria-label=${this.ariaLabel ?? (this.label || d)}
|
|
455
455
|
@click=${this._handlePrimaryClick}
|
|
456
456
|
@keydown=${this._handlePrimaryKeydown}
|
|
457
457
|
>
|
|
458
|
-
${this.label !== void 0 ? this.label :
|
|
458
|
+
${this.label !== void 0 ? this.label : c`<slot></slot>`}
|
|
459
459
|
</button>
|
|
460
460
|
|
|
461
461
|
<!-- Dropdown trigger button -->
|
|
@@ -464,7 +464,7 @@ let M = 0, i = class extends v {
|
|
|
464
464
|
class="split-button__trigger"
|
|
465
465
|
?disabled=${this.disabled}
|
|
466
466
|
aria-haspopup="menu"
|
|
467
|
-
aria-expanded=${this._open ? "true" :
|
|
467
|
+
aria-expanded=${this._open ? "true" : d}
|
|
468
468
|
aria-controls=${this._menuId}
|
|
469
469
|
aria-label=${this.triggerLabel}
|
|
470
470
|
type="button"
|
|
@@ -508,10 +508,10 @@ let M = 0, i = class extends v {
|
|
|
508
508
|
};
|
|
509
509
|
i.styles = [_, y];
|
|
510
510
|
n([
|
|
511
|
-
|
|
511
|
+
m(".split-button__menu")
|
|
512
512
|
], i.prototype, "_menuPanel", 2);
|
|
513
513
|
n([
|
|
514
|
-
|
|
514
|
+
m(".split-button__trigger")
|
|
515
515
|
], i.prototype, "_triggerButton", 2);
|
|
516
516
|
n([
|
|
517
517
|
g()
|
|
@@ -540,4 +540,4 @@ i = n([
|
|
|
540
540
|
export {
|
|
541
541
|
i as H
|
|
542
542
|
};
|
|
543
|
-
//# sourceMappingURL=hx-split-button-
|
|
543
|
+
//# sourceMappingURL=hx-split-button-CHGy4FUc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hx-split-button-BvwoG8h2.js","sources":["../../src/components/hx-split-button/hx-split-button.styles.ts","../../src/components/hx-split-button/hx-split-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSplitButtonStyles = css`\n :host {\n display: inline-block;\n position: relative;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Container ─── */\n\n .split-button {\n display: inline-flex;\n align-items: stretch;\n position: relative;\n }\n\n /* ─── Primary Button ─── */\n\n .split-button__primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);\n border-right: none;\n border-radius: var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0 0\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #2563eb));\n color: var(--hx-split-button-color, var(--hx-color-neutral-0, #ffffff));\n font-family: var(--hx-split-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-split-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n flex: 1 1 auto;\n }\n\n .split-button__primary:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__primary:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__primary:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__primary[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Button ─── */\n\n .split-button__trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);\n border-left: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-divider-color, var(--hx-color-primary-400, #3b82f6));\n border-radius: 0 var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem))\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0;\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #2563eb));\n color: var(--hx-split-button-color, var(--hx-color-neutral-0, #ffffff));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n user-select: none;\n -webkit-user-select: none;\n }\n\n .split-button__trigger:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__trigger:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__trigger:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__trigger[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Icon ─── */\n\n .split-button__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .split-button__chevron--open {\n transform: rotate(180deg);\n }\n\n /* ─── Size Variants ─── */\n\n /* sm */\n .split-button--sm .split-button__primary {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n .split-button--sm .split-button__trigger {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n /* md */\n .split-button--md .split-button__primary {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .split-button--md .split-button__trigger {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n /* lg */\n .split-button--lg .split-button__primary {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n .split-button--lg .split-button__trigger {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Variant: primary ─── */\n\n .split-button--primary .split-button__primary,\n .split-button--primary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-color: var(--hx-color-neutral-0, #ffffff);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-400, #3b82f6);\n }\n\n /* ─── Variant: secondary ─── */\n\n .split-button--secondary .split-button__primary,\n .split-button--secondary .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-border-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-divider-color: var(--hx-color-primary-300, #93c5fd);\n }\n\n .split-button--secondary .split-button__primary:hover,\n .split-button--secondary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-primary-50, #eff6ff);\n filter: none;\n }\n\n /* ─── Variant: tertiary ─── */\n\n .split-button--tertiary .split-button__primary,\n .split-button--tertiary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-neutral-100, #f1f5f9);\n --hx-split-button-color: var(--hx-color-neutral-900, #0f172a);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-neutral-300, #cbd5e1);\n }\n\n .split-button--tertiary .split-button__primary:hover,\n .split-button--tertiary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-200, #e2e8f0);\n filter: none;\n }\n\n /* ─── Variant: danger ─── */\n\n .split-button--danger .split-button__primary,\n .split-button--danger .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-error-500, #dc2626);\n --hx-split-button-color: var(--hx-color-neutral-0, #ffffff);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-error-400, #f87171);\n }\n\n .split-button--danger .split-button__primary:hover,\n .split-button--danger .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-error-600, #b91c1c);\n filter: none;\n }\n\n /* ─── Variant: ghost ─── */\n\n .split-button--ghost .split-button__primary,\n .split-button--ghost .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-200, #bfdbfe);\n }\n\n .split-button--ghost .split-button__primary:hover,\n .split-button--ghost .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-100, #f1f5f9);\n filter: none;\n }\n\n /* ─── Variant: outline ─── */\n\n .split-button--outline .split-button__primary,\n .split-button--outline .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-neutral-900, #0f172a);\n --hx-split-button-border-color: var(--hx-color-neutral-300, #cbd5e1);\n --hx-split-button-divider-color: var(--hx-color-neutral-300, #cbd5e1);\n }\n\n .split-button--outline .split-button__primary:hover,\n .split-button--outline .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-50, #f8fafc);\n filter: none;\n }\n\n /* ─── Dropdown Menu Panel ─── */\n\n @keyframes hx-split-button-menu-open {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .split-button__menu {\n display: none;\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n inset-inline-end: 0;\n min-width: 100%;\n max-height: var(--hx-split-button-menu-max-height, 18rem);\n overflow-y: auto;\n background-color: var(--hx-split-button-menu-bg, var(--hx-color-neutral-0, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-menu-border-color, var(--hx-color-neutral-200, #e2e8f0));\n border-radius: var(--hx-split-button-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-split-button-menu-shadow,\n 0 4px 6px -1px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1)),\n 0 2px 4px -2px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1))\n );\n padding: var(--hx-space-1, 0.25rem);\n z-index: var(--hx-z-index-dropdown, 200);\n }\n\n .split-button__menu--open {\n display: block;\n animation: hx-split-button-menu-open var(--hx-transition-fast, 150ms ease);\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .split-button__primary,\n .split-button__trigger,\n .split-button__chevron {\n transition: none;\n }\n\n .split-button__menu--open {\n animation: none;\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixSplitButtonStyles } from './hx-split-button.styles.js';\nimport type { HelixMenuItem } from '../hx-menu/hx-menu-item.js';\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nlet _hxSplitButtonIdCounter = 0;\n\n/**\n * A split button combining a primary action button with an attached dropdown\n * menu for secondary actions. Implements the ARIA menu button pattern for\n * full keyboard and screen reader support.\n *\n * @summary Primary action button with attached dropdown menu for secondary actions.\n *\n * @tag hx-split-button\n *\n * @slot - Primary button label text.\n * @slot menu - `hx-menu-item` children rendered in the dropdown panel.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the primary button is clicked and is not disabled.\n * @fires {CustomEvent<{value: string; label: string}>} hx-select - Dispatched when\n * a menu item is selected from the dropdown.\n *\n * @csspart button - The primary action button element.\n * @csspart trigger - The dropdown trigger button element.\n * @csspart menu - The dropdown menu panel.\n *\n * @cssprop [--hx-split-button-menu-max-height=18rem] - Maximum height of the dropdown menu panel before scrolling.\n * @cssprop [--hx-split-button-bg=var(--hx-color-primary-500)] - Background color for both buttons.\n * @cssprop [--hx-split-button-color=var(--hx-color-neutral-0)] - Text/icon color for both buttons.\n * @cssprop [--hx-split-button-border-color=transparent] - Border color.\n * @cssprop [--hx-split-button-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-split-button-divider-color=var(--hx-color-primary-400)] - Color of the divider between primary and trigger.\n * @cssprop [--hx-split-button-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-split-button-font-weight=var(--hx-font-weight-semibold)] - Font weight.\n * @cssprop [--hx-split-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-split-button-menu-bg=var(--hx-color-neutral-0)] - Dropdown menu background.\n * @cssprop [--hx-split-button-menu-border-color=var(--hx-color-neutral-200)] - Dropdown menu border color.\n * @cssprop [--hx-split-button-menu-border-radius=var(--hx-border-radius-md)] - Dropdown menu border radius.\n * @cssprop [--hx-split-button-menu-shadow] - Dropdown menu box shadow.\n */\n@customElement('hx-split-button')\nexport class HelixSplitButton extends LitElement {\n static override styles = [tokenStyles, helixSplitButtonStyles];\n\n // ─── Internal References ───\n\n /**\n * Reference to the dropdown menu panel element, used for positioning and focus management.\n * @internal\n */\n @query('.split-button__menu')\n private _menuPanel: HTMLElement | undefined;\n\n /**\n * Reference to the dropdown trigger button element, used to return focus after menu closes.\n * @internal\n */\n @query('.split-button__trigger')\n private _triggerButton: HTMLButtonElement | undefined;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether the dropdown menu is currently open.\n * @internal\n */\n @state() private _open = false;\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant of the split button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';\n\n /**\n * Size of the split button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the split button is disabled. Both the primary button and the\n * trigger are disabled when this is true.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Primary button label text. When set, overrides the default slot content.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * Accessible label for the dropdown trigger button. Override for localization.\n * @attr trigger-label\n */\n @property({ type: String, attribute: 'trigger-label' })\n triggerLabel = 'More actions';\n\n /**\n * Accessible label for the dropdown menu panel. Override for localization.\n * @attr menu-label\n */\n @property({ type: String, attribute: 'menu-label' })\n menuLabel = 'Secondary actions';\n\n // ─── Unique IDs ───\n\n /**\n * Stable unique ID for the dropdown menu panel element, used to wire aria-controls on the trigger button.\n * @internal\n */\n private readonly _menuId = `hx-split-button-menu-${++_hxSplitButtonIdCounter}`;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('click', this._handleOutsideClick);\n document.addEventListener('keydown', this._handleDocumentKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this._handleOutsideClick);\n document.removeEventListener('keydown', this._handleDocumentKeydown);\n }\n\n // ─── Outside-click / document keydown ───\n\n private readonly _handleOutsideClick = (e: MouseEvent): void => {\n if (!this._open) return;\n const target = e.target as Node;\n if (!this.contains(target) && target !== this) {\n this._closeMenu();\n }\n };\n\n private readonly _handleDocumentKeydown = (e: KeyboardEvent): void => {\n if (!this._open) return;\n if (e.key === 'Tab') {\n this._closeMenu();\n }\n };\n\n // ─── Primary Button Handlers ───\n\n private _handlePrimaryClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n /**\n * Dispatched when the primary button is clicked.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n }\n\n private _handlePrimaryKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Trigger Button Handlers ───\n\n private _handleTriggerClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n // Stop propagation so _handleOutsideClick does not immediately close.\n e.stopPropagation();\n this._toggleMenu();\n }\n\n private _handleTriggerKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Menu Key Navigation ───\n\n private _handleMenuKeydown(e: KeyboardEvent): void {\n const items = this._getMenuItems();\n if (items.length === 0) return;\n\n // document.activeElement returns the hx-menu-item host element when its\n // inner shadow DOM element has focus, which matches items[] directly.\n const currentIndex = items.findIndex((item) => item === document.activeElement);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n items[next]?.focus();\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n items[prev]?.focus();\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._closeMenu();\n this._triggerButton?.focus();\n break;\n }\n case 'Home': {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case 'End': {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n }\n\n // ─── Menu Item Selection ───\n\n private _handleMenuItemSelect(e: Event): void {\n const custom = e as CustomEvent<{ item: HelixMenuItem; value: string }>;\n this._closeMenu();\n this._triggerButton?.focus();\n\n const item = custom.detail.item;\n const label = item?.textContent?.trim() ?? '';\n\n /**\n * Dispatched when a menu item is selected.\n * @event hx-select\n */\n this.dispatchEvent(\n new CustomEvent<{ value: string; label: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { value: custom.detail.value, label },\n }),\n );\n }\n\n // ─── Menu Helpers ───\n\n private _openMenu(): void {\n if (this._open) return;\n this._open = true;\n // Focus the first enabled menu item after the panel renders\n this.updateComplete\n .then(() => {\n const items = this._getMenuItems();\n items[0]?.focus();\n })\n .catch(() => undefined);\n }\n\n private _closeMenu(): void {\n this._open = false;\n }\n\n private _toggleMenu(): void {\n if (this._open) {\n this._closeMenu();\n } else {\n this._openMenu();\n }\n }\n\n /**\n * Returns the enabled hx-menu-item host elements assigned to the `menu` slot.\n * HelixMenuItem overrides focus() to delegate to its inner element, so calling\n * .focus() on hosts works correctly. document.activeElement returns the host\n * element when the inner shadow element has focus, enabling correct index tracking.\n */\n private _getMenuItems(): HelixMenuItem[] {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"menu\"]');\n if (!slot) return [];\n\n return slot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HelixMenuItem =>\n el.tagName.toLowerCase() === 'hx-menu-item' && !(el as HelixMenuItem).disabled,\n );\n }\n\n // ─── Render ───\n\n override render() {\n const containerClasses = {\n 'split-button': true,\n [`split-button--${this.variant}`]: true,\n [`split-button--${this.size}`]: true,\n };\n\n const menuClasses = {\n 'split-button__menu': true,\n 'split-button__menu--open': this._open,\n };\n\n const chevronClasses = {\n 'split-button__chevron': true,\n 'split-button__chevron--open': this._open,\n };\n\n return html`\n <div class=${classMap(containerClasses)}>\n <!-- Primary action button -->\n <button\n part=\"button\"\n class=\"split-button__primary\"\n ?disabled=${this.disabled}\n type=\"button\"\n aria-label=${this.ariaLabel ?? this.label ?? nothing}\n @click=${this._handlePrimaryClick}\n @keydown=${this._handlePrimaryKeydown}\n >\n ${this.label !== undefined ? this.label : html`<slot></slot>`}\n </button>\n\n <!-- Dropdown trigger button -->\n <button\n part=\"trigger\"\n class=\"split-button__trigger\"\n ?disabled=${this.disabled}\n aria-haspopup=\"menu\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._menuId}\n aria-label=${this.triggerLabel}\n type=\"button\"\n @click=${this._handleTriggerClick}\n @keydown=${this._handleTriggerKeydown}\n >\n <span class=${classMap(chevronClasses)} aria-hidden=\"true\">\n <svg\n width=\"12\"\n height=\"8\"\n viewBox=\"0 0 12 8\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M1 1.5L6 6.5L11 1.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </button>\n\n <!-- Dropdown menu panel -->\n <div\n part=\"menu\"\n id=${this._menuId}\n class=${classMap(menuClasses)}\n role=\"menu\"\n aria-label=${this.menuLabel}\n @keydown=${this._handleMenuKeydown}\n @hx-item-select=${this._handleMenuItemSelect}\n >\n <slot name=\"menu\"></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-split-button': HelixSplitButton;\n }\n}\n"],"names":["helixSplitButtonStyles","css","_hxSplitButtonIdCounter","HelixSplitButton","LitElement","e","target","items","currentIndex","item","next","_a","prev","_b","_c","_d","_e","custom","label","slot","el","containerClasses","menuClasses","chevronClasses","html","classMap","nothing","tokenStyles","__decorateClass","query","state","property","customElement"],"mappings":";;;;AAEO,MAAMA,IAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
1
|
+
{"version":3,"file":"hx-split-button-CHGy4FUc.js","sources":["../../src/components/hx-split-button/hx-split-button.styles.ts","../../src/components/hx-split-button/hx-split-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSplitButtonStyles = css`\n :host {\n display: inline-block;\n position: relative;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* ─── Container ─── */\n\n .split-button {\n display: inline-flex;\n align-items: stretch;\n position: relative;\n }\n\n /* ─── Primary Button ─── */\n\n .split-button__primary {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--hx-space-2, 0.5rem);\n border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);\n border-right: none;\n border-radius: var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0 0\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #2563eb));\n color: var(--hx-split-button-color, var(--hx-color-neutral-0, #ffffff));\n font-family: var(--hx-split-button-font-family, var(--hx-font-family-sans, sans-serif));\n font-weight: var(--hx-split-button-font-weight, var(--hx-font-weight-semibold, 600));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n text-decoration: none;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n flex: 1 1 auto;\n }\n\n .split-button__primary:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__primary:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__primary:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__primary[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Button ─── */\n\n .split-button__trigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);\n border-left: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-divider-color, var(--hx-color-primary-400, #3b82f6));\n border-radius: 0 var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem))\n var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0;\n background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #2563eb));\n color: var(--hx-split-button-color, var(--hx-color-neutral-0, #ffffff));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n user-select: none;\n -webkit-user-select: none;\n }\n\n .split-button__trigger:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n z-index: 1;\n position: relative;\n }\n\n .split-button__trigger:hover {\n filter: brightness(var(--hx-filter-brightness-hover, 0.9));\n }\n\n .split-button__trigger:active {\n filter: brightness(var(--hx-filter-brightness-active, 0.8));\n }\n\n .split-button__trigger[disabled] {\n cursor: not-allowed;\n }\n\n /* ─── Trigger Icon ─── */\n\n .split-button__chevron {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .split-button__chevron--open {\n transform: rotate(180deg);\n }\n\n /* ─── Size Variants ─── */\n\n /* sm */\n .split-button--sm .split-button__primary {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n .split-button--sm .split-button__trigger {\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n min-height: var(--hx-size-8, 2rem);\n }\n\n /* md */\n .split-button--md .split-button__primary {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n font-size: var(--hx-font-size-md, 1rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n .split-button--md .split-button__trigger {\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n min-height: var(--hx-size-10, 2.5rem);\n }\n\n /* lg */\n .split-button--lg .split-button__primary {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-6, 1.5rem);\n font-size: var(--hx-font-size-lg, 1.125rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n .split-button--lg .split-button__trigger {\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n min-height: var(--hx-size-12, 3rem);\n }\n\n /* ─── Variant: primary ─── */\n\n .split-button--primary .split-button__primary,\n .split-button--primary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-color: var(--hx-color-neutral-0, #ffffff);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-400, #3b82f6);\n }\n\n /* ─── Variant: secondary ─── */\n\n .split-button--secondary .split-button__primary,\n .split-button--secondary .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-border-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-divider-color: var(--hx-color-primary-300, #93c5fd);\n }\n\n .split-button--secondary .split-button__primary:hover,\n .split-button--secondary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-primary-50, #eff6ff);\n filter: none;\n }\n\n /* ─── Variant: tertiary ─── */\n\n .split-button--tertiary .split-button__primary,\n .split-button--tertiary .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-neutral-100, #f1f5f9);\n --hx-split-button-color: var(--hx-color-neutral-900, #0f172a);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-neutral-300, #cbd5e1);\n }\n\n .split-button--tertiary .split-button__primary:hover,\n .split-button--tertiary .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-200, #e2e8f0);\n filter: none;\n }\n\n /* ─── Variant: danger ─── */\n\n .split-button--danger .split-button__primary,\n .split-button--danger .split-button__trigger {\n --hx-split-button-bg: var(--hx-color-error-500, #dc2626);\n --hx-split-button-color: var(--hx-color-neutral-0, #ffffff);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-error-400, #f87171);\n }\n\n .split-button--danger .split-button__primary:hover,\n .split-button--danger .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-error-600, #b91c1c);\n filter: none;\n }\n\n /* ─── Variant: ghost ─── */\n\n .split-button--ghost .split-button__primary,\n .split-button--ghost .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-primary-500, #2563eb);\n --hx-split-button-border-color: transparent;\n --hx-split-button-divider-color: var(--hx-color-primary-200, #bfdbfe);\n }\n\n .split-button--ghost .split-button__primary:hover,\n .split-button--ghost .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-100, #f1f5f9);\n filter: none;\n }\n\n /* ─── Variant: outline ─── */\n\n .split-button--outline .split-button__primary,\n .split-button--outline .split-button__trigger {\n --hx-split-button-bg: transparent;\n --hx-split-button-color: var(--hx-color-neutral-900, #0f172a);\n --hx-split-button-border-color: var(--hx-color-neutral-300, #cbd5e1);\n --hx-split-button-divider-color: var(--hx-color-neutral-300, #cbd5e1);\n }\n\n .split-button--outline .split-button__primary:hover,\n .split-button--outline .split-button__trigger:hover {\n --hx-split-button-bg: var(--hx-color-neutral-50, #f8fafc);\n filter: none;\n }\n\n /* ─── Dropdown Menu Panel ─── */\n\n @keyframes hx-split-button-menu-open {\n from {\n opacity: 0;\n transform: translateY(-4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .split-button__menu {\n display: none;\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n inset-inline-end: 0;\n min-width: 100%;\n max-height: var(--hx-split-button-menu-max-height, 18rem);\n overflow-y: auto;\n background-color: var(--hx-split-button-menu-bg, var(--hx-color-neutral-0, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-split-button-menu-border-color, var(--hx-color-neutral-200, #e2e8f0));\n border-radius: var(--hx-split-button-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-split-button-menu-shadow,\n 0 4px 6px -1px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1)),\n 0 2px 4px -2px var(--hx-overlay-black-10, rgba(0, 0, 0, 0.1))\n );\n padding: var(--hx-space-1, 0.25rem);\n z-index: var(--hx-z-index-dropdown, 200);\n }\n\n .split-button__menu--open {\n display: block;\n animation: hx-split-button-menu-open var(--hx-transition-fast, 150ms ease);\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .split-button__primary,\n .split-button__trigger,\n .split-button__chevron {\n transition: none;\n }\n\n .split-button__menu--open {\n animation: none;\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state, query } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixSplitButtonStyles } from './hx-split-button.styles.js';\nimport type { HelixMenuItem } from '../hx-menu/hx-menu-item.js';\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nlet _hxSplitButtonIdCounter = 0;\n\n/**\n * A split button combining a primary action button with an attached dropdown\n * menu for secondary actions. Implements the ARIA menu button pattern for\n * full keyboard and screen reader support.\n *\n * @summary Primary action button with attached dropdown menu for secondary actions.\n *\n * @tag hx-split-button\n *\n * @slot - Primary button label text.\n * @slot menu - `hx-menu-item` children rendered in the dropdown panel.\n *\n * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when\n * the primary button is clicked and is not disabled.\n * @fires {CustomEvent<{value: string; label: string}>} hx-select - Dispatched when\n * a menu item is selected from the dropdown.\n *\n * @csspart button - The primary action button element.\n * @csspart trigger - The dropdown trigger button element.\n * @csspart menu - The dropdown menu panel.\n *\n * @cssprop [--hx-split-button-menu-max-height=18rem] - Maximum height of the dropdown menu panel before scrolling.\n * @cssprop [--hx-split-button-bg=var(--hx-color-primary-500)] - Background color for both buttons.\n * @cssprop [--hx-split-button-color=var(--hx-color-neutral-0)] - Text/icon color for both buttons.\n * @cssprop [--hx-split-button-border-color=transparent] - Border color.\n * @cssprop [--hx-split-button-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-split-button-divider-color=var(--hx-color-primary-400)] - Color of the divider between primary and trigger.\n * @cssprop [--hx-split-button-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-split-button-font-weight=var(--hx-font-weight-semibold)] - Font weight.\n * @cssprop [--hx-split-button-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-split-button-menu-bg=var(--hx-color-neutral-0)] - Dropdown menu background.\n * @cssprop [--hx-split-button-menu-border-color=var(--hx-color-neutral-200)] - Dropdown menu border color.\n * @cssprop [--hx-split-button-menu-border-radius=var(--hx-border-radius-md)] - Dropdown menu border radius.\n * @cssprop [--hx-split-button-menu-shadow] - Dropdown menu box shadow.\n */\n@customElement('hx-split-button')\nexport class HelixSplitButton extends LitElement {\n static override styles = [tokenStyles, helixSplitButtonStyles];\n\n // ─── Internal References ───\n\n /**\n * Reference to the dropdown menu panel element, used for positioning and focus management.\n * @internal\n */\n @query('.split-button__menu')\n private _menuPanel: HTMLElement | undefined;\n\n /**\n * Reference to the dropdown trigger button element, used to return focus after menu closes.\n * @internal\n */\n @query('.split-button__trigger')\n private _triggerButton: HTMLButtonElement | undefined;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether the dropdown menu is currently open.\n * @internal\n */\n @state() private _open = false;\n\n // ─── Public Properties ───\n\n /**\n * Visual style variant of the split button.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';\n\n /**\n * Size of the split button.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether the split button is disabled. Both the primary button and the\n * trigger are disabled when this is true.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Primary button label text. When set, overrides the default slot content.\n * @attr label\n */\n @property({ type: String })\n label: string | undefined = undefined;\n\n /**\n * Accessible label for the dropdown trigger button. Override for localization.\n * @attr trigger-label\n */\n @property({ type: String, attribute: 'trigger-label' })\n triggerLabel = 'More actions';\n\n /**\n * Accessible label for the dropdown menu panel. Override for localization.\n * @attr menu-label\n */\n @property({ type: String, attribute: 'menu-label' })\n menuLabel = 'Secondary actions';\n\n // ─── Unique IDs ───\n\n /**\n * Stable unique ID for the dropdown menu panel element, used to wire aria-controls on the trigger button.\n * @internal\n */\n private readonly _menuId = `hx-split-button-menu-${++_hxSplitButtonIdCounter}`;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('click', this._handleOutsideClick);\n document.addEventListener('keydown', this._handleDocumentKeydown);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this._handleOutsideClick);\n document.removeEventListener('keydown', this._handleDocumentKeydown);\n }\n\n // ─── Outside-click / document keydown ───\n\n private readonly _handleOutsideClick = (e: MouseEvent): void => {\n if (!this._open) return;\n const target = e.target as Node;\n if (!this.contains(target) && target !== this) {\n this._closeMenu();\n }\n };\n\n private readonly _handleDocumentKeydown = (e: KeyboardEvent): void => {\n if (!this._open) return;\n if (e.key === 'Tab') {\n this._closeMenu();\n }\n };\n\n // ─── Primary Button Handlers ───\n\n private _handlePrimaryClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n /**\n * Dispatched when the primary button is clicked.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent<{ originalEvent: MouseEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { originalEvent: e },\n }),\n );\n }\n\n private _handlePrimaryKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Trigger Button Handlers ───\n\n private _handleTriggerClick(e: MouseEvent): void {\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n // Stop propagation so _handleOutsideClick does not immediately close.\n e.stopPropagation();\n this._toggleMenu();\n }\n\n private _handleTriggerKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n this._openMenu();\n }\n }\n\n // ─── Menu Key Navigation ───\n\n private _handleMenuKeydown(e: KeyboardEvent): void {\n const items = this._getMenuItems();\n if (items.length === 0) return;\n\n // document.activeElement returns the hx-menu-item host element when its\n // inner shadow DOM element has focus, which matches items[] directly.\n const currentIndex = items.findIndex((item) => item === document.activeElement);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n items[next]?.focus();\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n items[prev]?.focus();\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._closeMenu();\n this._triggerButton?.focus();\n break;\n }\n case 'Home': {\n e.preventDefault();\n items[0]?.focus();\n break;\n }\n case 'End': {\n e.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n }\n }\n\n // ─── Menu Item Selection ───\n\n private _handleMenuItemSelect(e: Event): void {\n const custom = e as CustomEvent<{ item: HelixMenuItem; value: string }>;\n this._closeMenu();\n this._triggerButton?.focus();\n\n const item = custom.detail.item;\n const label = item?.textContent?.trim() ?? '';\n\n /**\n * Dispatched when a menu item is selected.\n * @event hx-select\n */\n this.dispatchEvent(\n new CustomEvent<{ value: string; label: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { value: custom.detail.value, label },\n }),\n );\n }\n\n // ─── Menu Helpers ───\n\n private _openMenu(): void {\n if (this._open) return;\n this._open = true;\n // Focus the first enabled menu item after the panel renders\n this.updateComplete\n .then(() => {\n const items = this._getMenuItems();\n items[0]?.focus();\n })\n .catch(() => undefined);\n }\n\n private _closeMenu(): void {\n this._open = false;\n }\n\n private _toggleMenu(): void {\n if (this._open) {\n this._closeMenu();\n } else {\n this._openMenu();\n }\n }\n\n /**\n * Returns the enabled hx-menu-item host elements assigned to the `menu` slot.\n * HelixMenuItem overrides focus() to delegate to its inner element, so calling\n * .focus() on hosts works correctly. document.activeElement returns the host\n * element when the inner shadow element has focus, enabling correct index tracking.\n */\n private _getMenuItems(): HelixMenuItem[] {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"menu\"]');\n if (!slot) return [];\n\n return slot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HelixMenuItem =>\n el.tagName.toLowerCase() === 'hx-menu-item' && !(el as HelixMenuItem).disabled,\n );\n }\n\n // ─── Render ───\n\n override render() {\n const containerClasses = {\n 'split-button': true,\n [`split-button--${this.variant}`]: true,\n [`split-button--${this.size}`]: true,\n };\n\n const menuClasses = {\n 'split-button__menu': true,\n 'split-button__menu--open': this._open,\n };\n\n const chevronClasses = {\n 'split-button__chevron': true,\n 'split-button__chevron--open': this._open,\n };\n\n return html`\n <div class=${classMap(containerClasses)}>\n <!-- Primary action button -->\n <button\n part=\"button\"\n class=\"split-button__primary\"\n ?disabled=${this.disabled}\n type=\"button\"\n aria-label=${this.ariaLabel ?? (this.label || nothing)}\n @click=${this._handlePrimaryClick}\n @keydown=${this._handlePrimaryKeydown}\n >\n ${this.label !== undefined ? this.label : html`<slot></slot>`}\n </button>\n\n <!-- Dropdown trigger button -->\n <button\n part=\"trigger\"\n class=\"split-button__trigger\"\n ?disabled=${this.disabled}\n aria-haspopup=\"menu\"\n aria-expanded=${this._open ? 'true' : nothing}\n aria-controls=${this._menuId}\n aria-label=${this.triggerLabel}\n type=\"button\"\n @click=${this._handleTriggerClick}\n @keydown=${this._handleTriggerKeydown}\n >\n <span class=${classMap(chevronClasses)} aria-hidden=\"true\">\n <svg\n width=\"12\"\n height=\"8\"\n viewBox=\"0 0 12 8\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M1 1.5L6 6.5L11 1.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n </button>\n\n <!-- Dropdown menu panel -->\n <div\n part=\"menu\"\n id=${this._menuId}\n class=${classMap(menuClasses)}\n role=\"menu\"\n aria-label=${this.menuLabel}\n @keydown=${this._handleMenuKeydown}\n @hx-item-select=${this._handleMenuItemSelect}\n >\n <slot name=\"menu\"></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-split-button': HelixSplitButton;\n }\n}\n"],"names":["helixSplitButtonStyles","css","_hxSplitButtonIdCounter","HelixSplitButton","LitElement","e","target","items","currentIndex","item","next","_a","prev","_b","_c","_d","_e","custom","label","slot","el","containerClasses","menuClasses","chevronClasses","html","classMap","nothing","tokenStyles","__decorateClass","query","state","property","customElement"],"mappings":";;;;AAEO,MAAMA,IAAyBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}
|
|
@@ -91,8 +91,12 @@ const b = c`
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
.divider:focus-visible {
|
|
94
|
-
outline:
|
|
95
|
-
|
|
94
|
+
outline: var(--hx-focus-ring-width, 2px) solid
|
|
95
|
+
var(
|
|
96
|
+
--hx-split-panel-focus-ring-color,
|
|
97
|
+
var(--hx-focus-ring-color, var(--hx-color-primary-500))
|
|
98
|
+
);
|
|
99
|
+
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
96
100
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--_divider-hover-color) 30%, transparent);
|
|
97
101
|
}
|
|
98
102
|
|
|
@@ -149,14 +153,18 @@ const b = c`
|
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
.collapse-btn:focus-visible {
|
|
152
|
-
outline:
|
|
153
|
-
|
|
156
|
+
outline: var(--hx-focus-ring-width, 2px) solid
|
|
157
|
+
var(
|
|
158
|
+
--hx-split-panel-focus-ring-color,
|
|
159
|
+
var(--hx-focus-ring-color, var(--hx-color-primary-500))
|
|
160
|
+
);
|
|
161
|
+
outline-offset: var(--hx-focus-ring-offset, 2px);
|
|
154
162
|
}
|
|
155
163
|
`;
|
|
156
|
-
var
|
|
157
|
-
for (var r = l > 1 ? void 0 : l ?
|
|
164
|
+
var x = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, o = (t, i, n, l) => {
|
|
165
|
+
for (var r = l > 1 ? void 0 : l ? _(i, n) : i, a = t.length - 1, p; a >= 0; a--)
|
|
158
166
|
(p = t[a]) && (r = (l ? p(i, n, r) : p(r)) || r);
|
|
159
|
-
return l && r &&
|
|
167
|
+
return l && r && x(i, n, r), r;
|
|
160
168
|
};
|
|
161
169
|
let e = class extends u {
|
|
162
170
|
constructor() {
|
|
@@ -348,4 +356,4 @@ e = o([
|
|
|
348
356
|
export {
|
|
349
357
|
e as H
|
|
350
358
|
};
|
|
351
|
-
//# sourceMappingURL=hx-split-panel-
|
|
359
|
+
//# sourceMappingURL=hx-split-panel-DYtB45Tr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-split-panel-DYtB45Tr.js","sources":["../../src/components/hx-split-panel/hx-split-panel.styles.ts","../../src/components/hx-split-panel/hx-split-panel.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSplitPanelStyles = css`\n :host {\n display: flex;\n --_divider-size: var(--hx-split-panel-divider-size, 4px);\n --_divider-color: var(--hx-split-panel-divider-color, var(--hx-color-neutral-200));\n --_divider-hover-color: var(--hx-split-panel-divider-hover-color, var(--hx-color-primary-500));\n overflow: hidden;\n }\n\n :host([orientation='horizontal']) {\n flex-direction: row;\n width: 100%;\n height: 100%;\n }\n\n :host([orientation='vertical']) {\n flex-direction: column;\n width: 100%;\n height: 100%;\n }\n\n .panel {\n overflow: auto;\n min-width: 0;\n min-height: 0;\n }\n\n .panel--start {\n flex-shrink: 0;\n }\n\n .panel--end {\n flex: 1;\n }\n\n :host([orientation='horizontal']) .panel--start {\n height: 100%;\n }\n\n :host([orientation='vertical']) .panel--start {\n width: 100%;\n }\n\n /* ─── Divider Track (flex child wrapper) ─── */\n\n .divider-track {\n flex-shrink: 0;\n position: relative;\n overflow: visible;\n display: flex;\n align-items: stretch;\n }\n\n :host([orientation='horizontal']) .divider-track {\n width: var(--_divider-size);\n height: 100%;\n }\n\n :host([orientation='vertical']) .divider-track {\n width: 100%;\n height: var(--_divider-size);\n }\n\n /* ─── Divider (separator role — no interactive children) ─── */\n\n .divider {\n flex: 1;\n background-color: var(--_divider-color);\n cursor: col-resize;\n transition: background-color 0.15s ease;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n }\n\n :host([orientation='horizontal']) .divider {\n cursor: col-resize;\n }\n\n :host([orientation='vertical']) .divider {\n cursor: row-resize;\n }\n\n .divider:hover,\n .divider:focus-visible {\n background-color: var(--_divider-hover-color);\n }\n\n .divider:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-split-panel-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n box-shadow: 0 0 0 4px color-mix(in srgb, var(--_divider-hover-color) 30%, transparent);\n }\n\n :host([disabled]) .divider {\n cursor: default;\n pointer-events: none;\n }\n\n :host([disabled]) .divider:hover,\n :host([disabled]) .divider:focus-visible {\n background-color: var(--_divider-color);\n outline: none;\n box-shadow: none;\n }\n\n /* ─── Collapse Controls (siblings of separator, not children) ─── */\n\n .collapse-controls {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n z-index: 2;\n pointer-events: auto;\n }\n\n :host([orientation='vertical']) .collapse-controls {\n flex-direction: row;\n }\n\n .collapse-btn {\n background: var(--_divider-hover-color);\n border: 2px solid var(--hx-color-neutral-0);\n color: var(--hx-color-neutral-0);\n width: 20px;\n height: 20px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n padding: 0;\n line-height: 1;\n flex-shrink: 0;\n }\n\n .collapse-btn:hover {\n filter: brightness(1.1);\n }\n\n .collapse-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(\n --hx-split-panel-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-500))\n );\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n`;\n","import { LitElement, html, nothing, type PropertyValues } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixSplitPanelStyles } from './hx-split-panel.styles.js';\n\n/**\n * A resizable two-pane layout with a draggable divider.\n *\n * @summary Resizable split panel with start and end panes.\n *\n * @tag hx-split-panel\n *\n * @slot start - The first (start) panel content.\n * @slot end - The second (end) panel content.\n *\n * @csspart start - The start panel container.\n * @csspart divider - The draggable divider element.\n * @csspart end - The end panel container.\n *\n * @fires hx-reposition - Fired when the divider is moved. Detail: `{ position: number }`.\n *\n * @cssprop [--hx-split-panel-divider-size=4px] - Width (horizontal) or height (vertical) of the divider.\n * @cssprop [--hx-split-panel-divider-color=var(--hx-color-neutral-200)] - Default divider color.\n * @cssprop [--hx-split-panel-divider-hover-color=var(--hx-color-primary-500)] - Divider color on hover/focus.\n *\n * @example Drupal Twig usage:\n * ```twig\n * <hx-split-panel\n * position=\"50\"\n * orientation=\"horizontal\"\n * min=\"10\"\n * max=\"90\"\n * collapsible\n * >\n * <div slot=\"start\">{{ start_content }}</div>\n * <div slot=\"end\">{{ end_content }}</div>\n * </hx-split-panel>\n *\n * Attribute-settable: position, position-in-pixels, orientation, disabled, min, max, collapsible, collapsed\n * JS-only (complex types): snap (use .snap=${[25, 50, 75]} in Lit templates,\n * or snap=\"[25,50,75]\" as JSON string in Twig)\n * ```\n */\n@customElement('hx-split-panel')\nexport class HelixSplitPanel extends LitElement {\n static override styles = [tokenStyles, helixSplitPanelStyles];\n\n /**\n * Position of the divider as a percentage (0–100) of the start panel.\n * @attr position\n */\n @property({ type: Number, reflect: true })\n position = 50;\n\n /**\n * Position of the divider in pixels (alternative to `position`).\n * When set, takes precedence over `position` until the host is measured.\n * @attr position-in-pixels\n */\n @property({ type: Number, attribute: 'position-in-pixels' })\n positionInPixels: number | undefined;\n\n /**\n * Orientation of the split.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Minimum position as a percentage (0–100). Prevents full collapse of start panel.\n * @attr min\n */\n @property({ type: Number, reflect: true })\n min = 0;\n\n /**\n * Maximum position as a percentage (0–100). Prevents full expansion of start panel.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Snap points as an array of percentages. The divider snaps to the\n * nearest point within a 5% threshold.\n * Accepts JSON array string in HTML: snap=\"[25, 50, 75]\"\n * @attr snap\n */\n @property({\n attribute: 'snap',\n converter: {\n fromAttribute(value: string | null): number[] {\n if (!value) return [];\n try {\n const parsed = JSON.parse(value) as unknown;\n if (Array.isArray(parsed)) return (parsed as unknown[]).map(Number);\n return [];\n } catch {\n return value\n .split(',')\n .map((s) => Number(s.trim()))\n .filter((n) => !isNaN(n));\n }\n },\n toAttribute(value: number[]): string {\n return JSON.stringify(value);\n },\n },\n })\n snap: number[] = [];\n\n /**\n * When true, the divider cannot be dragged.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * When true, collapse/expand buttons appear on the divider.\n * @attr collapsible\n */\n @property({ type: Boolean, reflect: true })\n collapsible = false;\n\n /**\n * Which panel is collapsed: 'start', 'end', or null (not collapsed).\n * @attr collapsed\n */\n @property({ type: String, reflect: true })\n collapsed: 'start' | 'end' | null = null;\n\n /**\n * Whether the user is currently dragging the divider.\n * @internal\n */\n private _dragging = false;\n /**\n * The pointer coordinate (clientX or clientY) at the start of a drag gesture.\n * @internal\n */\n private _dragStart = 0;\n /**\n * The divider position percentage at the moment a drag gesture begins, used to compute deltas.\n * @internal\n */\n private _positionAtDragStart = 0;\n /**\n * The position saved before a collapse occurs, restored when the panel is expanded.\n * @internal\n */\n private _positionBeforeCollapse = 50;\n\n private _clamp(value: number): number {\n return Math.min(this.max, Math.max(this.min, value));\n }\n\n private _snapToPoint(value: number): number {\n if (!this.snap.length) return value;\n const threshold = 5;\n for (const point of this.snap) {\n if (Math.abs(value - point) <= threshold) return point;\n }\n return value;\n }\n\n private _setPosition(percent: number): void {\n const clamped = this._clamp(this._snapToPoint(percent));\n if (clamped === this.position) return;\n this.position = clamped;\n this.dispatchEvent(\n new CustomEvent<{ position: number }>('hx-reposition', {\n detail: { position: this.position },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _getHostSize(): number {\n if (this.orientation === 'horizontal') {\n return this.offsetWidth;\n }\n return this.offsetHeight;\n }\n\n /**\n * Initiates a drag gesture when the divider receives a pointerdown event.\n * @internal\n */\n private _onPointerDown = (e: PointerEvent): void => {\n if (this.disabled) return;\n const divider = e.currentTarget as HTMLElement;\n divider.setPointerCapture(e.pointerId);\n this._dragging = true;\n this._dragStart = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n this._positionAtDragStart = this.position;\n e.preventDefault();\n };\n\n /**\n * Updates the divider position during an active drag gesture.\n * @internal\n */\n private _onPointerMove = (e: PointerEvent): void => {\n if (!this._dragging) return;\n const current = this.orientation === 'horizontal' ? e.clientX : e.clientY;\n const delta = current - this._dragStart;\n const hostSize = this._getHostSize();\n if (hostSize === 0) return;\n const deltaPercent = (delta / hostSize) * 100;\n this._setPosition(this._positionAtDragStart + deltaPercent);\n };\n\n /**\n * Ends the drag gesture when the pointer is released.\n * @internal\n */\n private _onPointerUp = (): void => {\n this._dragging = false;\n };\n\n /**\n * Handles keyboard navigation on the divider — arrow keys adjust position, Home/End jump to min/max.\n * @internal\n */\n private _onKeyDown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n switch (e.key) {\n case 'ArrowLeft':\n case 'ArrowUp':\n e.preventDefault();\n this._setPosition(this.position - 1);\n break;\n case 'ArrowRight':\n case 'ArrowDown':\n e.preventDefault();\n this._setPosition(this.position + 1);\n break;\n case 'PageUp':\n e.preventDefault();\n this._setPosition(this.position + 10);\n break;\n case 'PageDown':\n e.preventDefault();\n this._setPosition(this.position - 10);\n break;\n case 'Home':\n e.preventDefault();\n this._setPosition(this.min);\n break;\n case 'End':\n e.preventDefault();\n this._setPosition(this.max);\n break;\n }\n };\n\n /**\n * Collapses the start panel by setting `collapsed` to `'start'`.\n * @internal\n */\n private _collapseStart = (): void => {\n this.collapsed = 'start';\n };\n\n /**\n * Collapses the end panel by setting `collapsed` to `'end'`.\n * @internal\n */\n private _collapseEnd = (): void => {\n this.collapsed = 'end';\n };\n\n /**\n * Expands a collapsed panel by resetting `collapsed` to null.\n * @internal\n */\n private _expand = (): void => {\n this.collapsed = null;\n };\n\n protected override willUpdate(changedProperties: PropertyValues): void {\n super.willUpdate(changedProperties);\n if (!changedProperties.has('collapsed')) return;\n\n const prev = changedProperties.get('collapsed');\n\n if (this.collapsed === 'start') {\n // Save restore point when transitioning from non-collapsed state (or initial render)\n if (prev === null || prev === undefined) this._positionBeforeCollapse = this.position;\n this._setPosition(this.min);\n } else if (this.collapsed === 'end') {\n if (prev === null || prev === undefined) this._positionBeforeCollapse = this.position;\n this._setPosition(this.max);\n } else if (this.collapsed === null && prev !== null && prev !== undefined) {\n // Only expand when transitioning from an explicitly collapsed state (not first render)\n this._setPosition(this._positionBeforeCollapse);\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (this.positionInPixels !== undefined) {\n // Convert pixel position to percentage after first paint\n requestAnimationFrame(() => {\n if (this.positionInPixels !== undefined) {\n const hostSize = this._getHostSize();\n if (hostSize > 0) {\n this._setPosition((this.positionInPixels / hostSize) * 100);\n }\n }\n });\n }\n }\n\n private _startPanelStyle(): string {\n if (this.orientation === 'horizontal') {\n return `width: ${this.position}%;`;\n }\n return `height: ${this.position}%;`;\n }\n\n override render() {\n return html`\n <div part=\"start\" class=\"panel panel--start\" style=${this._startPanelStyle()}>\n <slot name=\"start\"></slot>\n </div>\n <div class=\"divider-track\">\n <div\n part=\"divider\"\n class=\"divider\"\n role=\"separator\"\n aria-label=\"Resize panels\"\n aria-orientation=${this.orientation === 'horizontal' ? 'vertical' : 'horizontal'}\n aria-valuenow=${this.position}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-disabled=${this.disabled ? 'true' : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n @pointerdown=${this._onPointerDown}\n @pointermove=${this._onPointerMove}\n @pointerup=${this._onPointerUp}\n @keydown=${this._onKeyDown}\n ></div>\n ${this.collapsible\n ? this.collapsed\n ? html`<div class=\"collapse-controls\">\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=${`Expand ${this.collapsed} panel`}\n @click=${this._expand}\n >\n ${this.collapsed === 'start' ? '▶' : '◀'}\n </button>\n </div>`\n : html`<div class=\"collapse-controls\">\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=\"Collapse start panel\"\n @click=${this._collapseStart}\n >\n ◀\n </button>\n <button\n type=\"button\"\n class=\"collapse-btn\"\n aria-label=\"Collapse end panel\"\n @click=${this._collapseEnd}\n >\n ▶\n </button>\n </div>`\n : nothing}\n </div>\n <div part=\"end\" class=\"panel panel--end\">\n <slot name=\"end\"></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-split-panel': HelixSplitPanel;\n }\n}\n"],"names":["helixSplitPanelStyles","css","HelixSplitPanel","LitElement","e","delta","hostSize","deltaPercent","value","threshold","point","percent","clamped","changedProperties","prev","html","nothing","tokenStyles","__decorateClass","property","parsed","s","n","customElement"],"mappings":";;;AAEO,MAAMA,IAAwBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;AC0C9B,IAAMC,IAAN,cAA8BC,EAAW;AAAA,EAAzC,cAAA;AAAA,UAAA,GAAA,SAAA,GAQL,KAAA,WAAW,IAeX,KAAA,cAAyC,cAOzC,KAAA,MAAM,GAON,KAAA,MAAM,KA6BN,KAAA,OAAiB,CAAA,GAOjB,KAAA,WAAW,IAOX,KAAA,cAAc,IAOd,KAAA,YAAoC,MAMpC,KAAQ,YAAY,IAKpB,KAAQ,aAAa,GAKrB,KAAQ,uBAAuB,GAK/B,KAAQ,0BAA0B,IAuClC,KAAQ,iBAAiB,CAACC,MAA0B;AAClD,UAAI,KAAK,SAAU;AAEnB,MADgBA,EAAE,cACV,kBAAkBA,EAAE,SAAS,GACrC,KAAK,YAAY,IACjB,KAAK,aAAa,KAAK,gBAAgB,eAAeA,EAAE,UAAUA,EAAE,SACpE,KAAK,uBAAuB,KAAK,UACjCA,EAAE,eAAA;AAAA,IACJ,GAMA,KAAQ,iBAAiB,CAACA,MAA0B;AAClD,UAAI,CAAC,KAAK,UAAW;AAErB,YAAMC,KADU,KAAK,gBAAgB,eAAeD,EAAE,UAAUA,EAAE,WAC1C,KAAK,YACvBE,IAAW,KAAK,aAAA;AACtB,UAAIA,MAAa,EAAG;AACpB,YAAMC,IAAgBF,IAAQC,IAAY;AAC1C,WAAK,aAAa,KAAK,uBAAuBC,CAAY;AAAA,IAC5D,GAMA,KAAQ,eAAe,MAAY;AACjC,WAAK,YAAY;AAAA,IACnB,GAMA,KAAQ,aAAa,CAACH,MAA2B;AAC/C,UAAI,MAAK;AACT,gBAAQA,EAAE,KAAA;AAAA,UACR,KAAK;AAAA,UACL,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,WAAW,CAAC;AACnC;AAAA,UACF,KAAK;AAAA,UACL,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,WAAW,CAAC;AACnC;AAAA,UACF,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,WAAW,EAAE;AACpC;AAAA,UACF,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,WAAW,EAAE;AACpC;AAAA,UACF,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,GAAG;AAC1B;AAAA,UACF,KAAK;AACH,YAAAA,EAAE,eAAA,GACF,KAAK,aAAa,KAAK,GAAG;AAC1B;AAAA,QAAA;AAAA,IAEN,GAMA,KAAQ,iBAAiB,MAAY;AACnC,WAAK,YAAY;AAAA,IACnB,GAMA,KAAQ,eAAe,MAAY;AACjC,WAAK,YAAY;AAAA,IACnB,GAMA,KAAQ,UAAU,MAAY;AAC5B,WAAK,YAAY;AAAA,IACnB;AAAA,EAAA;AAAA,EA/HQ,OAAOI,GAAuB;AACpC,WAAO,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAKA,CAAK,CAAC;AAAA,EACrD;AAAA,EAEQ,aAAaA,GAAuB;AAC1C,QAAI,CAAC,KAAK,KAAK,OAAQ,QAAOA;AAC9B,UAAMC,IAAY;AAClB,eAAWC,KAAS,KAAK;AACvB,UAAI,KAAK,IAAIF,IAAQE,CAAK,KAAKD,EAAW,QAAOC;AAEnD,WAAOF;AAAA,EACT;AAAA,EAEQ,aAAaG,GAAuB;AAC1C,UAAMC,IAAU,KAAK,OAAO,KAAK,aAAaD,CAAO,CAAC;AACtD,IAAIC,MAAY,KAAK,aACrB,KAAK,WAAWA,GAChB,KAAK;AAAA,MACH,IAAI,YAAkC,iBAAiB;AAAA,QACrD,QAAQ,EAAE,UAAU,KAAK,SAAA;AAAA,QACzB,SAAS;AAAA,QACT,UAAU;AAAA,MAAA,CACX;AAAA,IAAA;AAAA,EAEL;AAAA,EAEQ,eAAuB;AAC7B,WAAI,KAAK,gBAAgB,eAChB,KAAK,cAEP,KAAK;AAAA,EACd;AAAA,EAkGmB,WAAWC,GAAyC;AAErE,QADA,MAAM,WAAWA,CAAiB,GAC9B,CAACA,EAAkB,IAAI,WAAW,EAAG;AAEzC,UAAMC,IAAOD,EAAkB,IAAI,WAAW;AAE9C,IAAI,KAAK,cAAc,WAEjBC,KAAS,SAA4B,KAAK,0BAA0B,KAAK,WAC7E,KAAK,aAAa,KAAK,GAAG,KACjB,KAAK,cAAc,SACxBA,KAAS,SAA4B,KAAK,0BAA0B,KAAK,WAC7E,KAAK,aAAa,KAAK,GAAG,KACjB,KAAK,cAAc,QAAQA,MAAS,QAAQA,MAAS,UAE9D,KAAK,aAAa,KAAK,uBAAuB;AAAA,EAElD;AAAA,EAES,oBAA0B;AACjC,UAAM,kBAAA,GACF,KAAK,qBAAqB,UAE5B,sBAAsB,MAAM;AAC1B,UAAI,KAAK,qBAAqB,QAAW;AACvC,cAAMR,IAAW,KAAK,aAAA;AACtB,QAAIA,IAAW,KACb,KAAK,aAAc,KAAK,mBAAmBA,IAAY,GAAG;AAAA,MAE9D;AAAA,IACF,CAAC;AAAA,EAEL;AAAA,EAEQ,mBAA2B;AACjC,WAAI,KAAK,gBAAgB,eAChB,UAAU,KAAK,QAAQ,OAEzB,WAAW,KAAK,QAAQ;AAAA,EACjC;AAAA,EAES,SAAS;AAChB,WAAOS;AAAA,2DACgD,KAAK,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BASrD,KAAK,gBAAgB,eAAe,aAAa,YAAY;AAAA,0BAChE,KAAK,QAAQ;AAAA,0BACb,KAAK,GAAG;AAAA,0BACR,KAAK,GAAG;AAAA,0BACR,KAAK,WAAW,SAASC,CAAO;AAAA,qBACrC,KAAK,WAAW,OAAO,GAAG;AAAA,yBACtB,KAAK,cAAc;AAAA,yBACnB,KAAK,cAAc;AAAA,uBACrB,KAAK,YAAY;AAAA,qBACnB,KAAK,UAAU;AAAA;AAAA,UAE1B,KAAK,cACH,KAAK,YACHD;AAAA;AAAA;AAAA;AAAA,+BAIiB,UAAU,KAAK,SAAS,QAAQ;AAAA,2BACpC,KAAK,OAAO;AAAA;AAAA,oBAEnB,KAAK,cAAc,UAAU,MAAM,GAAG;AAAA;AAAA,wBAG5CA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKa,KAAK,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAQnB,KAAK,YAAY;AAAA;AAAA;AAAA;AAAA,wBAKhCC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjB;AACF;AAnVad,EACK,SAAS,CAACe,GAAajB,CAAqB;AAO5DkB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAP9BjB,EAQX,WAAA,YAAA,CAAA;AAQAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,sBAAsB;AAAA,GAfhDjB,EAgBX,WAAA,oBAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAtB9BjB,EAuBX,WAAA,eAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GA7B9BjB,EA8BX,WAAA,OAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GApC9BjB,EAqCX,WAAA,OAAA,CAAA;AA6BAgB,EAAA;AAAA,EArBCC,EAAS;AAAA,IACR,WAAW;AAAA,IACX,WAAW;AAAA,MACT,cAAcX,GAAgC;AAC5C,YAAI,CAACA,EAAO,QAAO,CAAA;AACnB,YAAI;AACF,gBAAMY,IAAS,KAAK,MAAMZ,CAAK;AAC/B,iBAAI,MAAM,QAAQY,CAAM,IAAWA,EAAqB,IAAI,MAAM,IAC3D,CAAA;AAAA,QACT,QAAQ;AACN,iBAAOZ,EACJ,MAAM,GAAG,EACT,IAAI,CAACa,MAAM,OAAOA,EAAE,MAAM,CAAC,EAC3B,OAAO,CAACC,MAAM,CAAC,MAAMA,CAAC,CAAC;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,YAAYd,GAAyB;AACnC,eAAO,KAAK,UAAUA,CAAK;AAAA,MAC7B;AAAA,IAAA;AAAA,EACF,CACD;AAAA,GAjEUN,EAkEX,WAAA,QAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAxE/BjB,EAyEX,WAAA,YAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA/E/BjB,EAgFX,WAAA,eAAA,CAAA;AAOAgB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAtF9BjB,EAuFX,WAAA,aAAA,CAAA;AAvFWA,IAANgB,EAAA;AAAA,EADNK,EAAc,gBAAgB;AAAA,GAClBrB,CAAA;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { css as x, LitElement as _, nothing as $, html as m } from "lit";
|
|
2
|
-
import { property as
|
|
2
|
+
import { property as h, state as g, customElement as y } from "lit/decorators.js";
|
|
3
3
|
import { tokenStyles as w } from "@helixui/tokens/lit";
|
|
4
4
|
import { d as E } from "./dev-warn-YlwPHjtX.js";
|
|
5
|
-
const
|
|
5
|
+
const L = x`
|
|
6
6
|
:host {
|
|
7
7
|
display: block;
|
|
8
8
|
font-family: var(--hx-font-family-sans, sans-serif);
|
|
@@ -79,12 +79,12 @@ const k = x`
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
`;
|
|
82
|
-
var
|
|
83
|
-
for (var s = i > 1 ? void 0 : i ?
|
|
82
|
+
var k = Object.defineProperty, z = Object.getOwnPropertyDescriptor, p = (t, e, a, i) => {
|
|
83
|
+
for (var s = i > 1 ? void 0 : i ? z(e, a) : e, o = t.length - 1, r; o >= 0; o--)
|
|
84
84
|
(r = t[o]) && (s = (i ? r(e, a, s) : r(s)) || s);
|
|
85
|
-
return i && s &&
|
|
85
|
+
return i && s && k(e, a, s), s;
|
|
86
86
|
};
|
|
87
|
-
let I = 0,
|
|
87
|
+
let I = 0, d = class extends _ {
|
|
88
88
|
constructor() {
|
|
89
89
|
super(...arguments), this._id = `hx-tabs-${++I}`, this.orientation = "horizontal", this.activation = "automatic", this.label = "", this._activePanel = "", this._cachedTabs = null, this._cachedPanels = null, this._observer = null, this._handleTabSelect = (t) => {
|
|
90
90
|
if (!(t instanceof CustomEvent)) return;
|
|
@@ -104,21 +104,21 @@ let I = 0, h = class extends _ {
|
|
|
104
104
|
const a = this.orientation === "horizontal", i = a ? "ArrowLeft" : "ArrowUp", s = a ? "ArrowRight" : "ArrowDown";
|
|
105
105
|
if (![i, s, "Home", "End", " ", "Enter"].includes(t.key))
|
|
106
106
|
return;
|
|
107
|
-
const r = e.find((
|
|
107
|
+
const r = e.find((u) => u === document.activeElement);
|
|
108
108
|
if (t.key === " " || t.key === "Enter") {
|
|
109
109
|
r && (t.preventDefault(), this._activateTab(r), (S = (P = r.shadowRoot) == null ? void 0 : P.querySelector("button")) == null || S.focus());
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
112
112
|
t.preventDefault();
|
|
113
|
-
let
|
|
114
|
-
if (
|
|
115
|
-
const
|
|
116
|
-
|
|
113
|
+
let c = r ? e.indexOf(r) : -1;
|
|
114
|
+
if (c === -1) {
|
|
115
|
+
const u = e.find((O) => O.panel === this._activePanel);
|
|
116
|
+
c = u ? e.indexOf(u) : 0;
|
|
117
117
|
}
|
|
118
|
-
let
|
|
119
|
-
t.key === "Home" ?
|
|
120
|
-
const
|
|
121
|
-
|
|
118
|
+
let n;
|
|
119
|
+
t.key === "Home" ? n = 0 : t.key === "End" ? n = e.length - 1 : t.key === s ? n = (c + 1) % e.length : n = c <= 0 ? e.length - 1 : c - 1;
|
|
120
|
+
const f = e[n];
|
|
121
|
+
f && ((C = (T = f.shadowRoot) == null ? void 0 : T.querySelector("button")) == null || C.focus(), this.activation === "automatic" && this._activateTab(f));
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
// ─── Public API ───
|
|
@@ -160,7 +160,7 @@ let I = 0, h = class extends _ {
|
|
|
160
160
|
super.disconnectedCallback(), this.removeEventListener("hx-tab-select", this._handleTabSelect), this.removeEventListener("keydown", this._handleKeydown), (t = this._observer) == null || t.disconnect(), this._observer = null;
|
|
161
161
|
}
|
|
162
162
|
firstUpdated() {
|
|
163
|
-
if (this._syncTabsAndPanels(), !this._activePanel) {
|
|
163
|
+
if (this.label, this._syncTabsAndPanels(), !this._activePanel) {
|
|
164
164
|
const t = this._getEnabledTabs()[0];
|
|
165
165
|
t && this._activateTab(t, !1);
|
|
166
166
|
}
|
|
@@ -172,12 +172,15 @@ let I = 0, h = class extends _ {
|
|
|
172
172
|
_syncTabsAndPanels() {
|
|
173
173
|
const t = this._getTabs(), e = this._getPanels();
|
|
174
174
|
t.forEach((a, i) => {
|
|
175
|
+
var c;
|
|
175
176
|
const s = a.id || `hx-tab-${this._id}-${i}`;
|
|
176
177
|
a.id = s;
|
|
177
178
|
const o = a.panel, r = e.find((n) => n.name === o) ?? e[i];
|
|
178
179
|
if (r) {
|
|
179
180
|
const n = r.id || `hx-panel-${this._id}-${i}`;
|
|
180
|
-
r.id = n, a.controls = n
|
|
181
|
+
r.id = n, a.controls = n;
|
|
182
|
+
const f = ((c = a.textContent) == null ? void 0 : c.trim()) ?? "";
|
|
183
|
+
f ? (r.setAttribute("aria-label", f), r.removeAttribute("aria-labelledby")) : r.setAttribute("aria-labelledby", s);
|
|
181
184
|
}
|
|
182
185
|
}), this._updateTabsAndPanels();
|
|
183
186
|
}
|
|
@@ -245,22 +248,22 @@ let I = 0, h = class extends _ {
|
|
|
245
248
|
`;
|
|
246
249
|
}
|
|
247
250
|
};
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
],
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
],
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
],
|
|
258
|
-
|
|
251
|
+
d.styles = [w, L];
|
|
252
|
+
p([
|
|
253
|
+
h({ type: String, reflect: !0 })
|
|
254
|
+
], d.prototype, "orientation", 2);
|
|
255
|
+
p([
|
|
256
|
+
h({ type: String, attribute: "activation", reflect: !0 })
|
|
257
|
+
], d.prototype, "activation", 2);
|
|
258
|
+
p([
|
|
259
|
+
h({ type: String, reflect: !0 })
|
|
260
|
+
], d.prototype, "label", 2);
|
|
261
|
+
p([
|
|
259
262
|
g()
|
|
260
|
-
],
|
|
261
|
-
|
|
263
|
+
], d.prototype, "_activePanel", 2);
|
|
264
|
+
d = p([
|
|
262
265
|
y("hx-tabs")
|
|
263
|
-
],
|
|
266
|
+
], d);
|
|
264
267
|
const N = x`
|
|
265
268
|
:host {
|
|
266
269
|
display: inline-block;
|
|
@@ -354,7 +357,7 @@ const N = x`
|
|
|
354
357
|
}
|
|
355
358
|
}
|
|
356
359
|
`;
|
|
357
|
-
var D = Object.defineProperty, j = Object.getOwnPropertyDescriptor,
|
|
360
|
+
var D = Object.defineProperty, j = Object.getOwnPropertyDescriptor, b = (t, e, a, i) => {
|
|
358
361
|
for (var s = i > 1 ? void 0 : i ? j(e, a) : e, o = t.length - 1, r; o >= 0; o--)
|
|
359
362
|
(r = t[o]) && (s = (i ? r(e, a, s) : r(s)) || s);
|
|
360
363
|
return i && s && D(e, a, s), s;
|
|
@@ -406,25 +409,25 @@ let l = class extends _ {
|
|
|
406
409
|
}
|
|
407
410
|
};
|
|
408
411
|
l.styles = [w, N];
|
|
409
|
-
|
|
410
|
-
|
|
412
|
+
b([
|
|
413
|
+
h({ type: String, reflect: !0 })
|
|
411
414
|
], l.prototype, "panel", 2);
|
|
412
|
-
|
|
413
|
-
|
|
415
|
+
b([
|
|
416
|
+
h({ type: Boolean, reflect: !0 })
|
|
414
417
|
], l.prototype, "selected", 2);
|
|
415
|
-
|
|
416
|
-
|
|
418
|
+
b([
|
|
419
|
+
h({ type: Boolean, reflect: !0 })
|
|
417
420
|
], l.prototype, "disabled", 2);
|
|
418
|
-
|
|
419
|
-
|
|
421
|
+
b([
|
|
422
|
+
h({ type: String, attribute: !1 })
|
|
420
423
|
], l.prototype, "controls", 2);
|
|
421
|
-
|
|
424
|
+
b([
|
|
422
425
|
g()
|
|
423
426
|
], l.prototype, "_hasPrefixSlot", 2);
|
|
424
|
-
|
|
427
|
+
b([
|
|
425
428
|
g()
|
|
426
429
|
], l.prototype, "_hasSuffixSlot", 2);
|
|
427
|
-
l =
|
|
430
|
+
l = b([
|
|
428
431
|
y("hx-tab")
|
|
429
432
|
], l);
|
|
430
433
|
const H = x`
|
|
@@ -461,7 +464,7 @@ var K = Object.defineProperty, R = Object.getOwnPropertyDescriptor, A = (t, e, a
|
|
|
461
464
|
(r = t[o]) && (s = (i ? r(e, a, s) : r(s)) || s);
|
|
462
465
|
return i && s && K(e, a, s), s;
|
|
463
466
|
};
|
|
464
|
-
let
|
|
467
|
+
let v = class extends _ {
|
|
465
468
|
constructor() {
|
|
466
469
|
super(...arguments), this.name = "";
|
|
467
470
|
}
|
|
@@ -478,16 +481,16 @@ let u = class extends _ {
|
|
|
478
481
|
`;
|
|
479
482
|
}
|
|
480
483
|
};
|
|
481
|
-
|
|
484
|
+
v.styles = [w, H];
|
|
482
485
|
A([
|
|
483
|
-
|
|
484
|
-
],
|
|
485
|
-
|
|
486
|
+
h({ type: String, reflect: !0 })
|
|
487
|
+
], v.prototype, "name", 2);
|
|
488
|
+
v = A([
|
|
486
489
|
y("hx-tab-panel")
|
|
487
|
-
],
|
|
490
|
+
], v);
|
|
488
491
|
export {
|
|
489
492
|
l as H,
|
|
490
|
-
|
|
491
|
-
|
|
493
|
+
v as a,
|
|
494
|
+
d as b
|
|
492
495
|
};
|
|
493
|
-
//# sourceMappingURL=hx-tab-panel-
|
|
496
|
+
//# sourceMappingURL=hx-tab-panel-BRNcLICw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-tab-panel-BRNcLICw.js","sources":["../../src/components/hx-tabs/hx-tabs.styles.ts","../../src/components/hx-tabs/hx-tabs.ts","../../src/components/hx-tabs/hx-tab.styles.ts","../../src/components/hx-tabs/hx-tab.ts","../../src/components/hx-tabs/hx-tab-panel.styles.ts","../../src/components/hx-tabs/hx-tab-panel.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTabsStyles = css`\n :host {\n display: block;\n font-family: var(--hx-font-family-sans, sans-serif);\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Container ─── */\n\n .tabs {\n display: flex;\n flex-direction: column;\n gap: var(--hx-tabs-gap, 0);\n }\n\n :host([orientation='vertical']) .tabs {\n flex-direction: row;\n }\n\n /* ─── Tablist ─── */\n\n .tablist {\n display: flex;\n flex-direction: row;\n flex-wrap: nowrap;\n gap: 0;\n border-bottom: var(--hx-tabs-border-width, 1px) solid\n var(--hx-tabs-border-color, var(--hx-color-neutral-200, #e9ecef));\n overflow-x: auto;\n scrollbar-width: none;\n }\n\n .tablist::-webkit-scrollbar {\n display: none;\n }\n\n /* ─── Vertical Orientation ─── */\n\n :host([orientation='vertical']) {\n --_tab-indicator-bottom: 0px;\n --_tab-indicator-end: var(--hx-tabs-indicator-size, 2px);\n --_tab-indicator-bottom-color: transparent;\n --_tab-indicator-end-color: var(\n --hx-tabs-indicator-color,\n var(--hx-color-primary-500, #2563eb)\n );\n }\n\n :host([orientation='vertical']) .tablist {\n flex-direction: column;\n border-bottom: none;\n border-inline-end: var(--hx-tabs-border-width, 1px) solid\n var(--hx-tabs-border-color, var(--hx-color-neutral-200, #e9ecef));\n overflow-x: visible;\n overflow-y: auto;\n min-width: var(--hx-tabs-vertical-width, 12rem);\n flex-shrink: 0;\n }\n\n /* ─── Panels Container ─── */\n\n .panels {\n flex: 1 1 auto;\n min-width: 0;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .tablist {\n scroll-behavior: auto;\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixTabsStyles } from './hx-tabs.styles.js';\nimport type { HelixTab } from './hx-tab.js';\nimport type { HelixTabPanel } from './hx-tab-panel.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nlet _hxTabsIdCounter = 0;\n\n/**\n * A tabbed content organizer that manages a set of `<hx-tab>` and `<hx-tab-panel>` children.\n * Supports horizontal and vertical orientations, automatic and manual activation modes,\n * and full keyboard navigation per the ARIA Authoring Practices Guide.\n *\n * @summary Tab container that organizes content into selectable panels.\n *\n * @tag hx-tabs\n *\n * @slot tab - Slot for `<hx-tab>` elements. Rendered inside the tablist.\n * @slot - Default slot for `<hx-tab-panel>` elements.\n *\n * @fires {CustomEvent<{tabId: string, index: number}>} hx-tab-change - Dispatched when the active tab changes.\n *\n * @csspart tablist - The tablist container element.\n * @csspart panels - The panel content container element.\n *\n * @cssprop [--hx-tabs-border-color=var(--hx-color-neutral-200, #e9ecef)] - Tablist border color.\n * @cssprop [--hx-tabs-border-width=1px] - Tablist border width.\n * @cssprop [--hx-tabs-vertical-width=12rem] - Width of the tablist in vertical orientation.\n * @cssprop [--hx-tabs-gap=0] - Gap between the tablist and panels container.\n * @cssprop [--hx-tabs-tab-color=var(--hx-color-neutral-600, #495057)] - Inactive tab text color.\n * @cssprop [--hx-tabs-tab-active-color=var(--hx-color-primary-600, #1d4ed8)] - Active tab text color.\n * @cssprop [--hx-tabs-tab-hover-color=var(--hx-color-neutral-800, #212529)] - Tab hover text color.\n * @cssprop [--hx-tabs-tab-hover-bg=var(--hx-color-neutral-50, #f8f9fa)] - Tab hover background.\n * @cssprop [--hx-tabs-tab-font-size=var(--hx-font-size-md, 1rem)] - Tab font size.\n * @cssprop [--hx-tabs-tab-font-weight=var(--hx-font-weight-medium, 500)] - Tab font weight.\n * @cssprop [--hx-tabs-tab-active-font-weight=var(--hx-font-weight-semibold, 600)] - Active tab font weight.\n * @cssprop [--hx-tabs-tab-padding-x=var(--hx-space-4, 1rem)] - Horizontal tab padding.\n * @cssprop [--hx-tabs-tab-padding-y=var(--hx-space-2, 0.5rem)] - Vertical tab padding.\n * @cssprop [--hx-tabs-indicator-color=var(--hx-color-primary-500, #2563eb)] - Active indicator color.\n * @cssprop [--hx-tabs-indicator-size=2px] - Active indicator thickness.\n * @cssprop [--hx-tabs-focus-ring-color=var(--hx-focus-ring-color, #2563eb)] - Focus ring color for tabs and panels.\n * @cssprop [--hx-tabs-panel-padding=var(--hx-space-4, 1rem)] - Panel inner padding.\n * @cssprop [--hx-tabs-panel-color=var(--hx-color-neutral-700, #343a40)] - Panel text color.\n */\n@customElement('hx-tabs')\nexport class HelixTabs extends LitElement {\n static override styles = [tokenStyles, helixTabsStyles];\n\n // ─── Internal ID ───\n\n /** @internal */\n private _id = `hx-tabs-${++_hxTabsIdCounter}`;\n\n // ─── Properties ───\n\n /**\n * The layout orientation of the tabs.\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n /**\n * Controls how keyboard navigation activates tabs.\n * In `automatic` mode, focus also activates the tab.\n * In `manual` mode, focus moves independently; Space or Enter activates.\n * @attr activation\n */\n @property({ type: String, attribute: 'activation', reflect: true })\n activation: 'manual' | 'automatic' = 'automatic';\n\n /**\n * Accessible label for the tablist. Rendered as `aria-label` on the tablist container.\n * Provide a brief description of what the tabs represent (e.g., \"Patient record sections\").\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n // ─── State ───\n\n /** @internal */\n @state() private _activePanel = '';\n\n // ─── Child Accessors ───\n\n /** @internal */\n private _cachedTabs: HelixTab[] | null = null;\n /** @internal */\n private _cachedPanels: HelixTabPanel[] | null = null;\n /** @internal */\n private _observer: MutationObserver | null = null;\n\n // ─── Public API ───\n\n /**\n * Gets or sets the zero-based index of the currently selected tab.\n * Setting this programmatically activates the tab at the given index.\n */\n get selectedIndex(): number {\n return this._getTabs().findIndex((tab) => tab.panel === this._activePanel);\n }\n\n set selectedIndex(index: number) {\n const tab = this._getTabs()[index];\n if (tab && !tab.disabled) {\n this._activateTab(tab, true);\n }\n }\n\n private _getTabs(): HelixTab[] {\n if (!this._cachedTabs) {\n this._cachedTabs = Array.from(this.querySelectorAll(':scope > hx-tab')).filter(\n (el): el is HelixTab => el.tagName.toLowerCase() === 'hx-tab',\n );\n }\n return this._cachedTabs;\n }\n\n private _getPanels(): HelixTabPanel[] {\n if (!this._cachedPanels) {\n this._cachedPanels = Array.from(this.querySelectorAll(':scope > hx-tab-panel')).filter(\n (el): el is HelixTabPanel => el.tagName.toLowerCase() === 'hx-tab-panel',\n );\n }\n return this._cachedPanels;\n }\n\n private _getEnabledTabs(): HelixTab[] {\n return this._getTabs().filter((tab) => !tab.disabled);\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener('hx-tab-select', this._handleTabSelect);\n this.addEventListener('keydown', this._handleKeydown);\n // Watch for panel/name attribute changes on child tabs and panels\n this._observer = new MutationObserver(() => {\n this._cachedTabs = null;\n this._cachedPanels = null;\n this._syncTabsAndPanels();\n });\n this._observer.observe(this, {\n subtree: true,\n attributeFilter: ['panel', 'name'],\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('hx-tab-select', this._handleTabSelect);\n this.removeEventListener('keydown', this._handleKeydown);\n this._observer?.disconnect();\n this._observer = null;\n }\n\n override firstUpdated(): void {\n if (this.label === '') {\n devWarn(\n 'hx-tabs',\n 'No accessible label provided. Set the `label` attribute on hx-tabs to describe what the tabs represent (e.g., \"Patient record sections\"). An unlabeled tablist violates WCAG 4.1.2.',\n );\n }\n\n this._syncTabsAndPanels();\n // Activate the first enabled tab if none is selected\n if (!this._activePanel) {\n const firstEnabled = this._getEnabledTabs()[0];\n if (firstEnabled) {\n this._activateTab(firstEnabled, false);\n }\n }\n }\n\n override updated(changedProperties: Map<PropertyKey, unknown>): void {\n super.updated(changedProperties);\n if (changedProperties.has('_activePanel')) {\n this._updateTabsAndPanels();\n }\n }\n\n // ─── Tab / Panel Sync ───\n\n private _syncTabsAndPanels(): void {\n const tabs = this._getTabs();\n const panels = this._getPanels();\n\n tabs.forEach((tab, i) => {\n const tabId = tab.id || `hx-tab-${this._id}-${i}`;\n tab.id = tabId;\n\n // Connect tab to its panel by aria-controls\n const panelName = tab.panel;\n const panel = panels.find((p) => p.name === panelName) ?? panels[i];\n if (panel) {\n const panelId = panel.id || `hx-panel-${this._id}-${i}`;\n panel.id = panelId;\n // Set controls on the tab so aria-controls lands on the inner button (role=\"tab\")\n tab.controls = panelId;\n // Use aria-label instead of aria-labelledby to avoid shadow boundary failures.\n // aria-labelledby pointing to hx-tab host IDs fails because the host element's\n // accessible text is inside its shadow DOM (the inner <button>), which AT cannot\n // traverse via aria-labelledby references across shadow roots.\n const tabLabel = tab.textContent?.trim() ?? '';\n if (tabLabel) {\n panel.setAttribute('aria-label', tabLabel);\n panel.removeAttribute('aria-labelledby');\n } else {\n // Fall back to aria-labelledby if no text content is yet available;\n // this will be corrected on slotchange once content is assigned.\n panel.setAttribute('aria-labelledby', tabId);\n }\n }\n });\n\n this._updateTabsAndPanels();\n }\n\n private _updateTabsAndPanels(): void {\n const tabs = this._getTabs();\n const panels = this._getPanels();\n\n tabs.forEach((tab) => {\n const isSelected = tab.panel === this._activePanel;\n tab.selected = isSelected;\n // Dual tabindex is intentional: the inner button in hx-tab manages its own tabindex\n // via the `selected` property. We also set it on the host element for the roving\n // tabindex pattern so document.activeElement comparisons work correctly when the\n // inner button is focused. This is safe because the inner button is the only\n // focusable element in hx-tab's shadow DOM (WCAG 2.4.3).\n tab.tabIndex = isSelected ? 0 : -1;\n });\n\n panels.forEach((panel) => {\n const isActive = panel.name === this._activePanel;\n if (isActive) {\n panel.removeAttribute('hidden');\n panel.setAttribute('tabindex', '0');\n } else {\n panel.setAttribute('hidden', '');\n panel.setAttribute('tabindex', '-1');\n }\n });\n }\n\n // ─── Tab Activation ───\n\n private _activateTab(tab: HelixTab, dispatchEvent = true): void {\n if (tab.disabled) {\n return;\n }\n\n const tabs = this._getTabs();\n const previousPanel = this._activePanel;\n this._activePanel = tab.panel;\n\n if (dispatchEvent && previousPanel !== this._activePanel) {\n const index = tabs.indexOf(tab);\n /**\n * Dispatched when the active tab changes.\n * @event hx-tab-change\n */\n this.dispatchEvent(\n new CustomEvent('hx-tab-change', {\n bubbles: true,\n composed: true,\n detail: { tabId: tab.id, index },\n }),\n );\n }\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleTabSelect = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n e.stopPropagation();\n const tab = e\n .composedPath()\n .find((el): el is HelixTab => el instanceof Element && el.tagName.toLowerCase() === 'hx-tab');\n if (tab) {\n this._activateTab(tab);\n }\n };\n\n /** @internal */\n private _warnInvalidSlotContent(): void {\n const tabSlot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"tab\"]');\n const panelSlot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (tabSlot) {\n const invalid = tabSlot\n .assignedElements()\n .filter((el) => el.tagName.toLowerCase() !== 'hx-tab');\n if (invalid.length > 0) {\n devWarn(\n 'hx-tabs',\n `Slot \"tab\" expects <hx-tab> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n }\n if (panelSlot) {\n const invalid = panelSlot\n .assignedElements()\n .filter((el) => el.tagName.toLowerCase() !== 'hx-tab-panel');\n if (invalid.length > 0) {\n devWarn(\n 'hx-tabs',\n `Default slot expects <hx-tab-panel> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n }\n }\n\n /** @internal */\n private _handleSlotChange = (): void => {\n this._warnInvalidSlotContent();\n this._cachedTabs = null;\n this._cachedPanels = null;\n this._syncTabsAndPanels();\n // If the active panel was removed, fall back to the first enabled tab\n const panels = this._getPanels();\n const activePanelExists = panels.some((p) => p.name === this._activePanel);\n if (!activePanelExists) {\n const firstEnabled = this._getEnabledTabs()[0];\n if (firstEnabled) {\n this._activateTab(firstEnabled, false);\n } else {\n this._activePanel = '';\n }\n }\n };\n\n /** @internal */\n private _handleKeydown = (e: KeyboardEvent): void => {\n const enabledTabs = this._getEnabledTabs();\n if (enabledTabs.length === 0) {\n return;\n }\n\n const isHorizontal = this.orientation === 'horizontal';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n\n const isNavigationKey = [prevKey, nextKey, 'Home', 'End', ' ', 'Enter'].includes(e.key);\n if (!isNavigationKey) {\n return;\n }\n\n // Determine focused tab — when a button inside shadow DOM is focused,\n // document.activeElement returns the shadow host (hx-tab), not the inner button.\n const focusedTab = enabledTabs.find((tab) => tab === document.activeElement);\n\n if (e.key === ' ' || e.key === 'Enter') {\n if (focusedTab) {\n e.preventDefault();\n this._activateTab(focusedTab);\n focusedTab.shadowRoot?.querySelector('button')?.focus();\n }\n return;\n }\n\n e.preventDefault();\n\n let currentIndex = focusedTab ? enabledTabs.indexOf(focusedTab) : -1;\n // Fall back to the active tab's index if nothing is focused yet\n if (currentIndex === -1) {\n const activeTab = enabledTabs.find((tab) => tab.panel === this._activePanel);\n currentIndex = activeTab ? enabledTabs.indexOf(activeTab) : 0;\n }\n\n let nextIndex: number;\n\n if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = enabledTabs.length - 1;\n } else if (e.key === nextKey) {\n nextIndex = (currentIndex + 1) % enabledTabs.length;\n } else {\n // prevKey\n nextIndex = currentIndex <= 0 ? enabledTabs.length - 1 : currentIndex - 1;\n }\n\n const targetTab = enabledTabs[nextIndex];\n if (!targetTab) {\n return;\n }\n\n // Focus the tab button inside the shadow root\n targetTab.shadowRoot?.querySelector('button')?.focus();\n\n if (this.activation === 'automatic') {\n this._activateTab(targetTab);\n }\n };\n\n // ─── Render ───\n\n override render() {\n return html`\n <div class=\"tabs\">\n <div\n part=\"tablist\"\n class=\"tablist\"\n role=\"tablist\"\n aria-orientation=${this.orientation}\n aria-label=${this.label || nothing}\n >\n <slot name=\"tab\" @slotchange=${this._handleSlotChange}></slot>\n </div>\n <div part=\"panels\" class=\"panels\">\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tabs': HelixTabs;\n }\n}\n","import { css } from 'lit';\n\nexport const helixTabStyles = css`\n :host {\n display: inline-block;\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n * {\n box-sizing: border-box;\n }\n\n .tab {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-tabs-tab-padding-y, var(--hx-space-2, 0.5rem))\n var(--hx-tabs-tab-padding-x, var(--hx-space-4, 1rem));\n border: none;\n border-bottom: var(--_tab-indicator-bottom, var(--hx-tabs-indicator-size, 2px)) solid\n transparent;\n border-inline-end: var(--_tab-indicator-end, 0px) solid transparent;\n background: none;\n font-family: var(--hx-tabs-tab-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-tabs-tab-font-size, var(--hx-font-size-md, 1rem));\n font-weight: var(--hx-tabs-tab-font-weight, var(--hx-font-weight-medium, 500));\n color: var(--hx-tabs-tab-color, var(--hx-color-neutral-600, #495057));\n line-height: var(--hx-line-height-tight, 1.25);\n cursor: pointer;\n white-space: nowrap;\n user-select: none;\n -webkit-user-select: none;\n transition:\n color var(--hx-transition-fast, 150ms ease),\n border-color var(--hx-transition-fast, 150ms ease),\n border-inline-end-color var(--hx-transition-fast, 150ms ease),\n background-color var(--hx-transition-fast, 150ms ease);\n position: relative;\n }\n\n /* ─── Hover State ─── */\n\n .tab:not([aria-selected='true']):not([aria-disabled='true']):hover {\n color: var(--hx-tabs-tab-hover-color, var(--hx-color-neutral-800, #212529));\n background-color: var(--hx-tabs-tab-hover-bg, var(--hx-color-neutral-50, #f8f9fa));\n }\n\n /* ─── Selected State ─── */\n\n .tab[aria-selected='true'] {\n color: var(--hx-tabs-tab-active-color, var(--hx-color-primary-600, #1d4ed8));\n border-bottom-color: var(\n --_tab-indicator-bottom-color,\n var(--hx-tabs-indicator-color, var(--hx-color-primary-500, #2563eb))\n );\n border-inline-end-color: var(--_tab-indicator-end-color, transparent);\n font-weight: var(--hx-tabs-tab-active-font-weight, var(--hx-font-weight-semibold, 600));\n }\n\n /* ─── Focus State ─── */\n\n .tab:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tabs-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.125rem);\n }\n\n /* ─── Disabled State ─── */\n\n .tab[aria-disabled='true'] {\n cursor: not-allowed;\n color: var(--hx-color-neutral-400, #adb5bd);\n }\n\n /* ─── Prefix / Suffix Slots ─── */\n\n .tab__prefix,\n .tab__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .tab {\n transition: none;\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixTabStyles } from './hx-tab.styles.js';\n\n/**\n * An individual tab button, designed to be used inside an `<hx-tabs>` container.\n * Must be placed in the `tab` named slot of `<hx-tabs>`.\n *\n * @summary Presentational tab button that activates a corresponding panel.\n *\n * @tag hx-tab\n *\n * @slot - Default slot for the tab label text or content.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Icon or content rendered after the label.\n *\n * @csspart tab - The underlying button element.\n * @csspart prefix - The container for prefix slot content (e.g. icons).\n * @csspart suffix - The container for suffix slot content (e.g. badges).\n *\n * @cssprop [--hx-tabs-tab-color=var(--hx-color-neutral-600, #495057)] - Inactive tab text color.\n * @cssprop [--hx-tabs-tab-active-color=var(--hx-color-primary-600, #1d4ed8)] - Active tab text color.\n * @cssprop [--hx-tabs-tab-hover-color=var(--hx-color-neutral-800, #212529)] - Tab hover text color.\n * @cssprop [--hx-tabs-tab-hover-bg=var(--hx-color-neutral-50, #f8f9fa)] - Tab hover background.\n * @cssprop [--hx-tabs-tab-font-size=var(--hx-font-size-md, 1rem)] - Tab font size.\n * @cssprop [--hx-tabs-tab-font-weight=var(--hx-font-weight-medium, 500)] - Tab font weight.\n * @cssprop [--hx-tabs-tab-active-font-weight=var(--hx-font-weight-semibold, 600)] - Active tab font weight.\n * @cssprop [--hx-tabs-tab-padding-x=var(--hx-space-4, 1rem)] - Horizontal tab padding.\n * @cssprop [--hx-tabs-tab-padding-y=var(--hx-space-2, 0.5rem)] - Vertical tab padding.\n * @cssprop [--hx-tabs-indicator-color=var(--hx-color-primary-500, #2563eb)] - Active indicator color.\n * @cssprop [--hx-tabs-indicator-size=2px] - Active indicator thickness.\n * @cssprop [--hx-tabs-focus-ring-color=var(--hx-focus-ring-color, #2563eb)] - Focus ring color.\n */\n@customElement('hx-tab')\nexport class HelixTab extends LitElement {\n static override styles = [tokenStyles, helixTabStyles];\n\n // ─── Properties ───\n\n /**\n * The name of the `<hx-tab-panel>` this tab controls. Must match the `name`\n * attribute on the corresponding `<hx-tab-panel>`.\n * @attr panel\n */\n @property({ type: String, reflect: true })\n panel = '';\n\n /**\n * Whether this tab is currently selected. Managed by the parent `<hx-tabs>`.\n * @attr selected\n */\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n /**\n * Whether this tab is disabled. Prevents selection and keyboard navigation.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The id of the panel this tab controls. Set by the parent `<hx-tabs>` to establish the\n * aria-controls relationship on the inner button element (which carries role=\"tab\").\n * @internal\n */\n @property({ type: String, attribute: false })\n controls = '';\n\n // ─── Slot Visibility ───\n\n /** @internal */\n @state() private _hasPrefixSlot = false;\n /** @internal */\n @state() private _hasSuffixSlot = false;\n\n // ─── Event Handling ───\n\n private _handleClick(): void {\n if (this.disabled) {\n return;\n }\n /**\n * Internal event dispatched to signal tab selection to the parent container.\n * Not part of the public API.\n * @internal\n */\n this.dispatchEvent(\n new CustomEvent('hx-tab-select', {\n bubbles: true,\n composed: true,\n detail: { panel: this.panel },\n }),\n );\n }\n\n private _handlePrefixSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasPrefixSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n private _handleSuffixSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSuffixSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <button\n part=\"tab\"\n class=\"tab\"\n role=\"tab\"\n aria-selected=${this.selected ? 'true' : 'false'}\n aria-disabled=${this.disabled ? 'true' : 'false'}\n aria-controls=${this.controls || nothing}\n tabindex=${this.selected ? '0' : '-1'}\n @click=${this._handleClick}\n >\n <span part=\"prefix\" class=\"tab__prefix\" ?hidden=${!this._hasPrefixSlot}>\n <slot name=\"prefix\" @slotchange=${this._handlePrefixSlotChange}></slot>\n </span>\n <slot></slot>\n <span part=\"suffix\" class=\"tab__suffix\" ?hidden=${!this._hasSuffixSlot}>\n <slot name=\"suffix\" @slotchange=${this._handleSuffixSlotChange}></slot>\n </span>\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tab': HelixTab;\n }\n}\n","import { css } from 'lit';\n\nexport const helixTabPanelStyles = css`\n :host {\n display: block;\n }\n\n :host([hidden]) {\n display: none;\n }\n\n * {\n box-sizing: border-box;\n }\n\n :host(:focus-visible) {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tabs-focus-ring-color, var(--hx-focus-ring-color, #2563eb));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.125rem);\n }\n\n .panel {\n padding: var(--hx-tabs-panel-padding, var(--hx-space-4, 1rem));\n font-family: var(--hx-font-family-sans, sans-serif);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--hx-tabs-panel-color, var(--hx-color-neutral-700, #343a40));\n line-height: var(--hx-line-height-normal, 1.5);\n outline: none;\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixTabPanelStyles } from './hx-tab-panel.styles.js';\n\n/**\n * A content panel associated with an `<hx-tab>`, managed by a parent `<hx-tabs>`.\n *\n * @summary Tab content panel shown when its corresponding tab is selected.\n *\n * @tag hx-tab-panel\n *\n * @slot - Default slot for panel content.\n *\n * @csspart panel - The panel content wrapper.\n *\n * @cssprop [--hx-tabs-panel-padding=var(--hx-space-4, 1rem)] - Panel inner padding.\n * @cssprop [--hx-tabs-panel-color=var(--hx-color-neutral-700, #343a40)] - Panel text color.\n * @cssprop [--hx-tabs-focus-ring-color=var(--hx-focus-ring-color, #2563eb)] - Focus ring color.\n */\n@customElement('hx-tab-panel')\nexport class HelixTabPanel extends LitElement {\n static override styles = [tokenStyles, helixTabPanelStyles];\n\n // ─── Properties ───\n\n /**\n * The name that corresponds to the `panel` attribute on the associated `<hx-tab>`.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute('role', 'tabpanel');\n // tabindex is managed dynamically by the parent hx-tabs component:\n // active panels get tabindex=\"0\", hidden panels get tabindex=\"-1\"\n }\n\n // ─── Render ───\n\n override render() {\n return html`\n <div part=\"panel\" class=\"panel\">\n <slot></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tab-panel': HelixTabPanel;\n }\n}\n"],"names":["helixTabsStyles","css","_hxTabsIdCounter","HelixTabs","LitElement","e","tab","el","p","firstEnabled","enabledTabs","isHorizontal","prevKey","nextKey","focusedTab","_b","_a","currentIndex","activeTab","nextIndex","targetTab","_d","_c","index","changedProperties","tabs","panels","tabId","panelName","panel","panelId","tabLabel","isSelected","dispatchEvent","previousPanel","tabSlot","panelSlot","invalid","devWarn","html","nothing","tokenStyles","__decorateClass","property","state","customElement","helixTabStyles","HelixTab","slot","helixTabPanelStyles","HelixTabPanel"],"mappings":"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"}
|