@helixui/library 3.2.0-next.78 → 3.2.0-next.81
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 +25 -10
- package/dist/components/hx-button/index.js +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.d.ts +7 -5
- package/dist/components/hx-side-nav/hx-nav-item.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-side-nav.d.ts +5 -4
- package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
- package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
- package/dist/components/hx-side-nav/index.js +1 -1
- package/dist/css/helix-all.css +13 -5
- package/dist/css/helix-core.css +5 -5
- package/dist/css/helix-navigation.css +8 -0
- package/dist/css/hx-button.css +5 -5
- package/dist/css/hx-side-nav.css +8 -0
- package/dist/css/index.css +1 -1
- package/dist/css/manifest.json +3 -1
- package/dist/index.js +2 -2
- package/dist/shared/{hx-button-YeUzCe6e.js → hx-button-kWxjKqo-.js} +6 -6
- package/dist/shared/hx-button-kWxjKqo-.js.map +1 -0
- package/dist/shared/{hx-nav-item-BqML5BAh.js → hx-nav-item-CMyMv5Gv.js} +98 -60
- package/dist/shared/hx-nav-item-CMyMv5Gv.js.map +1 -0
- package/figma-inventory.json +65 -29
- package/package.json +2 -2
- package/dist/shared/hx-button-YeUzCe6e.js.map +0 -1
- package/dist/shared/hx-nav-item-BqML5BAh.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css as A, html as c, nothing as h } from "lit";
|
|
2
|
-
import { property as p, customElement as
|
|
3
|
-
import { H as
|
|
4
|
-
import { c as
|
|
2
|
+
import { property as p, customElement as T, state as $ } from "lit/decorators.js";
|
|
3
|
+
import { H as I } from "./helix-element-BNEYeiys.js";
|
|
4
|
+
import { c as E } from "./id-counter-DuX8vsui.js";
|
|
5
5
|
const S = A`
|
|
6
6
|
:host {
|
|
7
7
|
display: block;
|
|
@@ -168,22 +168,30 @@ const S = A`
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
.side-nav__toggle {
|
|
171
|
+
forced-color-adjust: none;
|
|
172
|
+
background-color: ButtonFace;
|
|
171
173
|
color: ButtonText;
|
|
172
174
|
border: 1px solid ButtonText;
|
|
173
175
|
}
|
|
174
176
|
|
|
177
|
+
.side-nav__toggle:hover {
|
|
178
|
+
background-color: Highlight;
|
|
179
|
+
color: HighlightText;
|
|
180
|
+
border-color: Highlight;
|
|
181
|
+
}
|
|
182
|
+
|
|
175
183
|
.side-nav__toggle:focus-visible {
|
|
176
184
|
outline: 3px solid Highlight;
|
|
177
185
|
outline-offset: 2px;
|
|
178
186
|
}
|
|
179
187
|
}
|
|
180
188
|
`;
|
|
181
|
-
var
|
|
182
|
-
for (var t = i > 1 ? void 0 : i ?
|
|
183
|
-
(n = e[l]) && (t = (i ? n(
|
|
184
|
-
return i && t &&
|
|
189
|
+
var H = Object.defineProperty, B = Object.getOwnPropertyDescriptor, u = (e, o, a, i) => {
|
|
190
|
+
for (var t = i > 1 ? void 0 : i ? B(o, a) : o, l = e.length - 1, n; l >= 0; l--)
|
|
191
|
+
(n = e[l]) && (t = (i ? n(o, a, t) : n(t)) || t);
|
|
192
|
+
return i && t && H(o, a, t), t;
|
|
185
193
|
};
|
|
186
|
-
let x = class extends
|
|
194
|
+
let x = class extends I {
|
|
187
195
|
constructor() {
|
|
188
196
|
super(...arguments), this.collapsed = !1, this.label = "Main Navigation";
|
|
189
197
|
}
|
|
@@ -199,11 +207,11 @@ let x = class extends E {
|
|
|
199
207
|
*/
|
|
200
208
|
/** @internal */
|
|
201
209
|
_propagateCollapsedToChildren() {
|
|
202
|
-
var
|
|
203
|
-
const e = (
|
|
210
|
+
var a;
|
|
211
|
+
const e = (a = this.shadowRoot) == null ? void 0 : a.querySelector("slot:not([name])");
|
|
204
212
|
if (!e) return;
|
|
205
|
-
const
|
|
206
|
-
for (const i of
|
|
213
|
+
const o = e.assignedElements({ flatten: !0 }).filter((i) => i.tagName.toLowerCase() === "hx-nav-item");
|
|
214
|
+
for (const i of o)
|
|
207
215
|
i instanceof HTMLElement && (this.collapsed ? i.setAttribute("data-collapsed", "") : i.removeAttribute("data-collapsed"));
|
|
208
216
|
}
|
|
209
217
|
/**
|
|
@@ -225,16 +233,16 @@ let x = class extends E {
|
|
|
225
233
|
_handleKeydown(e) {
|
|
226
234
|
var b, w, y, k, C;
|
|
227
235
|
if (!["ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft", "Home", "End"].includes(e.key)) return;
|
|
228
|
-
const
|
|
229
|
-
if (!
|
|
230
|
-
const i =
|
|
231
|
-
(
|
|
236
|
+
const a = (b = this.shadowRoot) == null ? void 0 : b.querySelector("slot:not([name])");
|
|
237
|
+
if (!a) return;
|
|
238
|
+
const i = a.assignedElements({ flatten: !0 }).filter(
|
|
239
|
+
(r) => r.tagName.toLowerCase() === "hx-nav-item" && !r.hasAttribute("disabled")
|
|
232
240
|
);
|
|
233
241
|
if (i.length === 0) return;
|
|
234
242
|
const t = [];
|
|
235
|
-
for (const
|
|
236
|
-
if (t.push(
|
|
237
|
-
const s = (w =
|
|
243
|
+
for (const r of i)
|
|
244
|
+
if (t.push(r), r.hasAttribute("expanded")) {
|
|
245
|
+
const s = (w = r.shadowRoot) == null ? void 0 : w.querySelector('slot[name="children"]');
|
|
238
246
|
if (s) {
|
|
239
247
|
const g = s.assignedElements({ flatten: !0 }).filter(
|
|
240
248
|
(m) => m.tagName.toLowerCase() === "hx-nav-item" && !m.hasAttribute("disabled")
|
|
@@ -245,22 +253,22 @@ let x = class extends E {
|
|
|
245
253
|
if (t.length === 0) return;
|
|
246
254
|
const l = document.activeElement;
|
|
247
255
|
let n = -1;
|
|
248
|
-
for (let
|
|
249
|
-
const s = t[
|
|
256
|
+
for (let r = 0; r < t.length; r++) {
|
|
257
|
+
const s = t[r];
|
|
250
258
|
if (s && (s === l || s.contains(l) || ((y = s.shadowRoot) == null ? void 0 : y.contains(l)) === !0)) {
|
|
251
|
-
n =
|
|
259
|
+
n = r;
|
|
252
260
|
break;
|
|
253
261
|
}
|
|
254
262
|
}
|
|
255
263
|
if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
256
264
|
e.preventDefault();
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
265
|
+
const r = n >= 0 ? t[n] : null;
|
|
266
|
+
if (!r) return;
|
|
259
267
|
if (e.key === "ArrowRight") {
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
-
else if (
|
|
263
|
-
const s = (k =
|
|
268
|
+
if (r.hasAttribute("expanded") === !1 && r.querySelector('[slot="children"]'))
|
|
269
|
+
r.setAttribute("expanded", ""), r.expanded = !0;
|
|
270
|
+
else if (r.hasAttribute("expanded")) {
|
|
271
|
+
const s = (k = r.shadowRoot) == null ? void 0 : k.querySelector('slot[name="children"]');
|
|
264
272
|
if (s) {
|
|
265
273
|
const g = s.assignedElements({ flatten: !0 }).find(
|
|
266
274
|
(m) => m.tagName.toLowerCase() === "hx-nav-item" && !m.hasAttribute("disabled")
|
|
@@ -271,10 +279,10 @@ let x = class extends E {
|
|
|
271
279
|
}
|
|
272
280
|
}
|
|
273
281
|
}
|
|
274
|
-
} else if (
|
|
275
|
-
|
|
282
|
+
} else if (r.hasAttribute("expanded"))
|
|
283
|
+
r.removeAttribute("expanded"), r.expanded = !1;
|
|
276
284
|
else {
|
|
277
|
-
const s =
|
|
285
|
+
const s = r.closest("hx-nav-item:not(:scope)") ?? ((C = r.parentElement) == null ? void 0 : C.closest("hx-nav-item")) ?? null;
|
|
278
286
|
s && !s.hasAttribute("disabled") && s.focus();
|
|
279
287
|
}
|
|
280
288
|
return;
|
|
@@ -346,9 +354,9 @@ u([
|
|
|
346
354
|
p({ type: String })
|
|
347
355
|
], x.prototype, "label", 2);
|
|
348
356
|
x = u([
|
|
349
|
-
|
|
357
|
+
T("hx-side-nav")
|
|
350
358
|
], x);
|
|
351
|
-
const
|
|
359
|
+
const N = A`
|
|
352
360
|
:host {
|
|
353
361
|
display: block;
|
|
354
362
|
/* The host background must be a concrete color so that axe-core can
|
|
@@ -606,8 +614,38 @@ const H = A`
|
|
|
606
614
|
/* ─── Forced Colors (Windows High Contrast) ─── */
|
|
607
615
|
|
|
608
616
|
@media (forced-colors: active) {
|
|
617
|
+
/*
|
|
618
|
+
* Bespoke block — sole owner of forced-colors deference for hx-nav-item
|
|
619
|
+
* (the forcedColorsInteractive mixin is intentionally NOT composed; XOR
|
|
620
|
+
* rule in styles/forced-colors.ts). Mirrors the mixin's interactive
|
|
621
|
+
* contract (ButtonFace / ButtonText / Highlight on hover, GrayText on
|
|
622
|
+
* disabled) for the .nav-item__link interactive surface, then layers the
|
|
623
|
+
* component-specific active-state border and tooltip border on top.
|
|
624
|
+
*/
|
|
625
|
+
.nav-item__link {
|
|
626
|
+
forced-color-adjust: none;
|
|
627
|
+
background-color: ButtonFace;
|
|
628
|
+
color: ButtonText;
|
|
629
|
+
border: 1px solid ButtonText;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.nav-item__link:hover {
|
|
633
|
+
background-color: Highlight;
|
|
634
|
+
color: HighlightText;
|
|
635
|
+
border-color: Highlight;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
:host([disabled]) {
|
|
639
|
+
opacity: 1;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
:host([disabled]) .nav-item__link {
|
|
643
|
+
color: GrayText;
|
|
644
|
+
border-color: GrayText;
|
|
645
|
+
}
|
|
646
|
+
|
|
609
647
|
:host([active]) .nav-item__link {
|
|
610
|
-
border:
|
|
648
|
+
border-color: Highlight;
|
|
611
649
|
}
|
|
612
650
|
|
|
613
651
|
.nav-item__link:focus-visible {
|
|
@@ -620,22 +658,22 @@ const H = A`
|
|
|
620
658
|
}
|
|
621
659
|
}
|
|
622
660
|
`;
|
|
623
|
-
var
|
|
624
|
-
for (var t = i > 1 ? void 0 : i ?
|
|
625
|
-
(n = e[l]) && (t = (i ? n(
|
|
626
|
-
return i && t &&
|
|
661
|
+
var D = Object.defineProperty, j = Object.getOwnPropertyDescriptor, v = (e, o, a, i) => {
|
|
662
|
+
for (var t = i > 1 ? void 0 : i ? j(o, a) : o, l = e.length - 1, n; l >= 0; l--)
|
|
663
|
+
(n = e[l]) && (t = (i ? n(o, a, t) : n(t)) || t);
|
|
664
|
+
return i && t && D(o, a, t), t;
|
|
627
665
|
};
|
|
628
|
-
const
|
|
629
|
-
let d = class extends
|
|
666
|
+
const L = E("hx-nav-item");
|
|
667
|
+
let d = class extends I {
|
|
630
668
|
constructor() {
|
|
631
|
-
super(...arguments), this._tooltipId = `${
|
|
669
|
+
super(...arguments), this._tooltipId = `${L()}-tooltip`, this.href = "", this.active = !1, this.expanded = !1, this.disabled = !1, this._hasChildren = !1, this._isCollapsed = !1;
|
|
632
670
|
}
|
|
633
671
|
// ─── Attribute Observer ───
|
|
634
672
|
static get observedAttributes() {
|
|
635
673
|
return [...super.observedAttributes, "data-collapsed"];
|
|
636
674
|
}
|
|
637
|
-
attributeChangedCallback(e,
|
|
638
|
-
super.attributeChangedCallback(e,
|
|
675
|
+
attributeChangedCallback(e, o, a) {
|
|
676
|
+
super.attributeChangedCallback(e, o, a), e === "data-collapsed" && (this._isCollapsed = a !== null);
|
|
639
677
|
}
|
|
640
678
|
// ─── Public API ───
|
|
641
679
|
/**
|
|
@@ -645,22 +683,22 @@ let d = class extends E {
|
|
|
645
683
|
* direct shadowRoot queries.
|
|
646
684
|
*/
|
|
647
685
|
focus(e) {
|
|
648
|
-
var
|
|
649
|
-
const
|
|
650
|
-
|
|
686
|
+
var a;
|
|
687
|
+
const o = (a = this.shadowRoot) == null ? void 0 : a.querySelector('[part="link"]');
|
|
688
|
+
o ? o.focus(e) : super.focus(e);
|
|
651
689
|
}
|
|
652
690
|
// ─── Slot Change Handler ───
|
|
653
691
|
/** @internal */
|
|
654
692
|
_onChildrenSlotChange(e) {
|
|
655
|
-
const
|
|
656
|
-
this._hasChildren =
|
|
693
|
+
const o = e.target;
|
|
694
|
+
this._hasChildren = o.assignedNodes({ flatten: !0 }).length > 0;
|
|
657
695
|
}
|
|
658
696
|
// ─── Private Helpers ───
|
|
659
697
|
/** @internal */
|
|
660
698
|
_getDirectText() {
|
|
661
699
|
return Array.from(this.childNodes).filter((e) => e.nodeType === Node.TEXT_NODE).map((e) => {
|
|
662
|
-
var
|
|
663
|
-
return ((
|
|
700
|
+
var o;
|
|
701
|
+
return ((o = e.textContent) == null ? void 0 : o.trim()) ?? "";
|
|
664
702
|
}).filter(Boolean).join(" ");
|
|
665
703
|
}
|
|
666
704
|
/** @internal */
|
|
@@ -679,7 +717,7 @@ let d = class extends E {
|
|
|
679
717
|
}
|
|
680
718
|
// ─── Render ───
|
|
681
719
|
render() {
|
|
682
|
-
const e = this._getDirectText(),
|
|
720
|
+
const e = this._getDirectText(), o = c`
|
|
683
721
|
<span part="icon" class="nav-item__icon">
|
|
684
722
|
<slot name="icon"></slot>
|
|
685
723
|
</span>
|
|
@@ -691,7 +729,7 @@ let d = class extends E {
|
|
|
691
729
|
</span>
|
|
692
730
|
${this._hasChildren ? this._renderExpandArrow() : h}
|
|
693
731
|
${this._isCollapsed ? c`<span id=${this._tooltipId} class="nav-item__tooltip" role="tooltip">${e}</span>` : h}
|
|
694
|
-
`,
|
|
732
|
+
`, a = this.href && !this._hasChildren ? c`<a
|
|
695
733
|
part="link"
|
|
696
734
|
class="nav-item__link"
|
|
697
735
|
href=${this.href}
|
|
@@ -700,7 +738,7 @@ let d = class extends E {
|
|
|
700
738
|
aria-describedby=${this._isCollapsed ? this._tooltipId : h}
|
|
701
739
|
tabindex=${this.disabled ? "-1" : "0"}
|
|
702
740
|
>
|
|
703
|
-
${
|
|
741
|
+
${o}
|
|
704
742
|
</a>` : c`<button
|
|
705
743
|
part="link"
|
|
706
744
|
class="nav-item__link"
|
|
@@ -710,11 +748,11 @@ let d = class extends E {
|
|
|
710
748
|
tabindex=${this.disabled ? "-1" : "0"}
|
|
711
749
|
@click=${this._handleToggle}
|
|
712
750
|
>
|
|
713
|
-
${
|
|
751
|
+
${o}
|
|
714
752
|
</button>`;
|
|
715
753
|
return c`
|
|
716
754
|
<div class="nav-item">
|
|
717
|
-
${
|
|
755
|
+
${a}
|
|
718
756
|
<div part="children" class="nav-item__children" role="group">
|
|
719
757
|
<div class="nav-item__children-inner">
|
|
720
758
|
<slot name="children" @slotchange=${this._onChildrenSlotChange}></slot>
|
|
@@ -724,7 +762,7 @@ let d = class extends E {
|
|
|
724
762
|
`;
|
|
725
763
|
}
|
|
726
764
|
};
|
|
727
|
-
d.styles = [
|
|
765
|
+
d.styles = [N];
|
|
728
766
|
v([
|
|
729
767
|
p({ type: String })
|
|
730
768
|
], d.prototype, "href", 2);
|
|
@@ -738,16 +776,16 @@ v([
|
|
|
738
776
|
p({ type: Boolean, reflect: !0 })
|
|
739
777
|
], d.prototype, "disabled", 2);
|
|
740
778
|
v([
|
|
741
|
-
|
|
779
|
+
$()
|
|
742
780
|
], d.prototype, "_hasChildren", 2);
|
|
743
781
|
v([
|
|
744
|
-
|
|
782
|
+
$()
|
|
745
783
|
], d.prototype, "_isCollapsed", 2);
|
|
746
784
|
d = v([
|
|
747
|
-
|
|
785
|
+
T("hx-nav-item")
|
|
748
786
|
], d);
|
|
749
787
|
export {
|
|
750
788
|
d as H,
|
|
751
789
|
x as a
|
|
752
790
|
};
|
|
753
|
-
//# sourceMappingURL=hx-nav-item-
|
|
791
|
+
//# sourceMappingURL=hx-nav-item-CMyMv5Gv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hx-nav-item-CMyMv5Gv.js","sources":["../../src/components/hx-side-nav/hx-side-nav.styles.ts","../../src/components/hx-side-nav/hx-side-nav.ts","../../src/components/hx-side-nav/hx-nav-item.styles.ts","../../src/components/hx-side-nav/hx-nav-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSideNavStyles = css`\n :host {\n display: block;\n height: 100%;\n /* Mirror the nav background and text on the host so slotted light-DOM\n content (header, footer slots) inherits the correct dark surface color.\n Without this, axe-core cannot resolve the background for slotted nodes\n and evaluates their text against the page white background, producing\n false-positive color-contrast violations (WCAG 2.1 AA). */\n background-color: var(--hx-side-nav-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #ffffff));\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Nav Container ─── */\n\n .side-nav {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: var(--hx-side-nav-width, 16rem);\n background-color: var(--hx-side-nav-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-side-nav-color, var(--hx-color-text-inverse, #ffffff));\n transition: width var(--hx-transition-normal, 300ms) ease;\n overflow: hidden;\n border-inline-end: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-border-strong, #8e9c98));\n }\n\n /* ─── Collapsed State ─── */\n\n :host([collapsed]) .side-nav {\n width: var(--hx-side-nav-collapsed-width, 3.5rem);\n }\n\n /* ─── Header ─── */\n\n .side-nav__header {\n display: flex;\n align-items: center;\n padding: var(--hx-side-nav-header-padding, var(--hx-space-4, 1rem));\n flex-shrink: 0;\n min-height: var(--hx-space-14, 3.5rem);\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-border-strong, #8e9c98));\n overflow: hidden;\n }\n\n :host([collapsed]) .side-nav__header {\n justify-content: center;\n padding: var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Body ─── */\n\n .side-nav__body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--hx-space-2, 0.5rem) 0;\n }\n\n /* ─── Footer ─── */\n\n .side-nav__footer {\n display: flex;\n align-items: center;\n padding: var(--hx-side-nav-footer-padding, var(--hx-space-4, 1rem));\n flex-shrink: 0;\n min-height: var(--hx-space-14, 3.5rem);\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-side-nav-border-color, var(--hx-color-border-strong, #8e9c98));\n overflow: hidden;\n }\n\n :host([collapsed]) .side-nav__footer {\n justify-content: center;\n padding: var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Toggle Button ─── */\n\n .side-nav__toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--hx-space-8, 2rem);\n height: var(--hx-space-8, 2rem);\n margin-inline-start: auto;\n flex-shrink: 0;\n padding: 0;\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n background: transparent;\n color: var(--hx-side-nav-toggle-color, var(--hx-color-text-inverse, #ffffff));\n cursor: pointer;\n transition:\n background-color var(--hx-transition-fast, 150ms) ease,\n color var(--hx-transition-fast, 150ms) ease;\n }\n\n .side-nav__toggle:hover {\n background-color: var(\n --hx-color-border-on-dark-subtle,\n rgba(255, 255, 255, 0.1)\n ); /* fallback for browsers without color-mix() */\n color: var(--hx-side-nav-toggle-hover-color, var(--hx-color-text-inverse, #ffffff));\n }\n\n @supports (color: color-mix(in srgb, red 50%, blue)) {\n .side-nav__toggle:hover {\n background-color: color-mix(in srgb, currentColor 15%, transparent);\n }\n }\n\n .side-nav__toggle:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-side-nav-focus-ring-color, var(--hx-focus-ring-color, #6ab1b1));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .side-nav__toggle svg {\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n fill: currentColor;\n flex-shrink: 0;\n transition: transform var(--hx-transition-normal, 300ms) ease;\n }\n\n :host([collapsed]) .side-nav__toggle svg {\n transform: rotate(180deg);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .side-nav {\n transition: none;\n }\n\n .side-nav__toggle {\n transition: none;\n }\n\n .side-nav__toggle svg {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .side-nav {\n border-inline-end-color: CanvasText;\n }\n\n .side-nav__header {\n border-bottom-color: CanvasText;\n }\n\n .side-nav__footer {\n border-top-color: CanvasText;\n }\n\n .side-nav__toggle {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n\n .side-nav__toggle:hover {\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n }\n\n .side-nav__toggle:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n }\n`;\n","import { html, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixSideNavStyles } from './hx-side-nav.styles.js';\n\n/**\n * A collapsible left-side navigation panel with nested menu item support.\n * Designed for clinical portals, admin dashboards, and department navigation.\n *\n * @summary Collapsible side navigation panel for enterprise healthcare applications.\n *\n * @tag hx-side-nav\n *\n * @slot - Default slot for hx-nav-item children.\n * @slot header - Logo or branding content.\n * @slot footer - User profile or settings content.\n *\n * @fires {CustomEvent<{ collapsed: boolean }>} hx-collapse - Dispatched when the nav collapses to icon-only mode.\n * @fires {CustomEvent<{ collapsed: boolean }>} hx-expand - Dispatched when the nav expands to full width.\n *\n * @csspart nav - The outer nav element.\n * @csspart header - The header section.\n * @csspart body - The scrollable body section.\n * @csspart footer - The footer section.\n * @csspart toggle - The collapse/expand toggle button.\n *\n * @cssprop [--hx-side-nav-width=16rem] - Full expanded width.\n * @cssprop [--hx-side-nav-collapsed-width=3.5rem] - Collapsed icon-only width.\n * @cssprop [--hx-side-nav-bg=var(--hx-color-surface-inverse)] - Background color.\n * @cssprop [--hx-side-nav-color=var(--hx-color-text-inverse)] - Text color.\n * @cssprop [--hx-side-nav-border-color=var(--hx-color-border-strong)] - Border color.\n * @cssprop [--hx-side-nav-header-padding=var(--hx-space-4)] - Header padding.\n * @cssprop [--hx-side-nav-footer-padding=var(--hx-space-4)] - Footer padding.\n * @cssprop [--hx-side-nav-toggle-color=var(--hx-color-text-inverse)] - Toggle button icon color (resting).\n * @cssprop [--hx-side-nav-toggle-hover-color=var(--hx-color-text-inverse)] - Toggle button icon color on hover.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-transition-normal] - Transition timing.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-14] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-8] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-overlay-white-10] - Overlay color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-space-5] - Spacing token.\n */\n@customElement('hx-side-nav')\nexport class HelixSideNav extends HelixElement {\n // 3.2.1: forced-colors deference is owned by the bespoke @media block in\n // hx-side-nav.styles.ts (toggle button, header/footer borders). Do NOT also\n // compose forcedColorsInteractive — XOR rule per the mixin docstring.\n static override styles = [helixSideNavStyles];\n\n // ─── Properties ───\n\n /**\n * When true, the nav collapses to show icons only.\n * @attr collapsed\n */\n @property({ type: Boolean, reflect: true })\n collapsed = false;\n\n /**\n * The accessible label for the nav landmark.\n * @attr label\n */\n @property({ type: String })\n label = 'Main Navigation';\n\n // ─── Lifecycle ───\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('collapsed')) {\n this._propagateCollapsedToChildren();\n }\n }\n\n // ─── Collapsed State Propagation ───\n\n /**\n * Propagates the collapsed state to all slotted hx-nav-item children by\n * setting or removing the `data-collapsed` attribute. This allows child\n * items to respond to collapsed mode via their CSS selectors.\n */\n /** @internal */\n private _propagateCollapsedToChildren(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const navItems = slot\n .assignedElements({ flatten: true })\n .filter((el) => el.tagName.toLowerCase() === 'hx-nav-item');\n\n for (const item of navItems) {\n if (!(item instanceof HTMLElement)) continue;\n if (this.collapsed) {\n item.setAttribute('data-collapsed', '');\n } else {\n item.removeAttribute('data-collapsed');\n }\n }\n }\n\n /**\n * Handles the default slot's slotchange event so that if items are added\n * after initial render, they immediately receive the correct collapsed state.\n */\n /** @internal */\n private _onDefaultSlotChange(): void {\n this._propagateCollapsedToChildren();\n }\n\n // ─── Keyboard Navigation ───\n\n /**\n * Implements roving tabindex-style ArrowUp/ArrowDown keyboard navigation\n * among direct hx-nav-item children in the body slot. Disabled items are\n * skipped. Focus is applied to the interactive element inside the shadow DOM\n * of each item (anchor or button with part=\"link\").\n */\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n const validKeys = ['ArrowDown', 'ArrowUp', 'ArrowRight', 'ArrowLeft', 'Home', 'End'];\n if (!validKeys.includes(e.key)) return;\n\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const topLevelItems = slot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n\n if (topLevelItems.length === 0) return;\n\n // Build a flattened list of navigable items: direct children plus visible\n // child items from expanded parent items (per ARIA APG tree pattern).\n const navItems: HTMLElement[] = [];\n for (const item of topLevelItems) {\n navItems.push(item);\n // If this item is expanded, include its non-disabled children\n if (item.hasAttribute('expanded')) {\n const childrenSlot =\n item.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"children\"]');\n if (childrenSlot) {\n const childItems = childrenSlot\n .assignedElements({ flatten: true })\n .filter(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n navItems.push(...childItems);\n }\n }\n }\n\n if (navItems.length === 0) return;\n\n // Find which item currently contains focus\n const activeEl = document.activeElement;\n let currentIndex = -1;\n for (let i = 0; i < navItems.length; i++) {\n const item = navItems[i];\n if (!item) continue;\n if (\n item === activeEl ||\n item.contains(activeEl) ||\n item.shadowRoot?.contains(activeEl) === true\n ) {\n currentIndex = i;\n break;\n }\n }\n\n // Handle ArrowRight/ArrowLeft for expand/collapse (ARIA APG tree pattern)\n if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {\n e.preventDefault();\n const currentItem = currentIndex >= 0 ? navItems[currentIndex] : null;\n if (!currentItem) return;\n\n if (e.key === 'ArrowRight') {\n // If the item has children and is collapsed, expand it\n if (\n currentItem.hasAttribute('expanded') === false &&\n currentItem.querySelector('[slot=\"children\"]')\n ) {\n currentItem.setAttribute('expanded', '');\n (currentItem as HTMLElement & { expanded?: boolean }).expanded = true;\n } else if (currentItem.hasAttribute('expanded')) {\n // Already expanded: move focus to first child item\n const childrenSlot =\n currentItem.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"children\"]');\n if (childrenSlot) {\n const firstChild = childrenSlot\n .assignedElements({ flatten: true })\n .find(\n (el): el is HTMLElement =>\n el.tagName.toLowerCase() === 'hx-nav-item' && !el.hasAttribute('disabled'),\n );\n if (firstChild) {\n firstChild.focus();\n return;\n }\n }\n }\n } else {\n // ArrowLeft: if expanded, collapse; if collapsed or non-expandable, find parent\n if (currentItem.hasAttribute('expanded')) {\n currentItem.removeAttribute('expanded');\n (currentItem as HTMLElement & { expanded?: boolean }).expanded = false;\n } else {\n // Move focus to parent item if this item is a child in another item's slot\n const parentNavItem =\n currentItem.closest<HTMLElement>('hx-nav-item:not(:scope)') ??\n currentItem.parentElement?.closest<HTMLElement>('hx-nav-item') ??\n null;\n if (parentNavItem && !parentNavItem.hasAttribute('disabled')) {\n parentNavItem.focus();\n }\n }\n }\n return;\n }\n\n e.preventDefault();\n\n let nextIndex: number;\n if (e.key === 'ArrowDown') {\n nextIndex = currentIndex < navItems.length - 1 ? currentIndex + 1 : 0;\n } else if (e.key === 'ArrowUp') {\n nextIndex = currentIndex > 0 ? currentIndex - 1 : navItems.length - 1;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else {\n nextIndex = navItems.length - 1;\n }\n\n const targetItem = navItems[nextIndex];\n if (!targetItem) return;\n // WCAG 2.1.1: call the public focus() method on the nav item rather than\n // piercing its Shadow DOM directly. hx-nav-item.focus() delegates to the\n // internal [part=\"link\"] element, preserving shadow encapsulation.\n targetItem.focus();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleToggle(): void {\n this.collapsed = !this.collapsed;\n\n if (this.collapsed) {\n /**\n * Dispatched when the nav collapses to icon-only mode.\n * @event hx-collapse\n */\n this.dispatchEvent(\n new CustomEvent<{ collapsed: boolean }>('hx-collapse', {\n bubbles: true,\n composed: true,\n detail: { collapsed: true },\n }),\n );\n } else {\n /**\n * Dispatched when the nav expands to full width.\n * @event hx-expand\n */\n this.dispatchEvent(\n new CustomEvent<{ collapsed: boolean }>('hx-expand', {\n bubbles: true,\n composed: true,\n detail: { collapsed: false },\n }),\n );\n }\n }\n\n // ─── Render ───\n\n /** @internal */\n private _renderToggleIcon() {\n return html`<svg viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <path\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n />\n </svg>`;\n }\n\n override render() {\n return html`\n <nav part=\"nav\" class=\"side-nav\" aria-label=${this.label}>\n <div part=\"header\" class=\"side-nav__header\">\n <slot name=\"header\"></slot>\n <button\n part=\"toggle\"\n class=\"side-nav__toggle\"\n aria-label=${this.collapsed ? 'Expand navigation' : 'Collapse navigation'}\n aria-expanded=${!this.collapsed}\n @click=${this._handleToggle}\n >\n ${this._renderToggleIcon()}\n </button>\n </div>\n\n <div part=\"body\" class=\"side-nav__body\" id=\"side-nav-body\" @keydown=${this._handleKeydown}>\n <slot @slotchange=${this._onDefaultSlotChange}></slot>\n </div>\n\n <div part=\"footer\" class=\"side-nav__footer\">\n <slot name=\"footer\"></slot>\n </div>\n </nav>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-side-nav': HelixSideNav;\n }\n}\n\nexport type { HelixSideNav as HxSideNav };\n","import { css } from 'lit';\n\nexport const helixNavItemStyles = css`\n :host {\n display: block;\n /* The host background must be a concrete color so that axe-core can\n resolve text contrast ratios for shadow-DOM content correctly.\n surface-inverse + text-inverse flip per mode: dark-on-light in dark\n mode, light-on-dark in light mode. */\n background-color: var(--hx-nav-item-host-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-nav-item-color, var(--hx-color-text-inverse, #ffffff));\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Nav Item ─── */\n\n .nav-item {\n display: flex;\n flex-direction: column;\n }\n\n /* ─── Link / Button ─── */\n\n .nav-item__link {\n display: flex;\n align-items: center;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-nav-item-padding, var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem));\n min-height: var(--hx-space-10, 2.5rem);\n text-decoration: none;\n color: var(--hx-nav-item-color, var(--hx-color-text-inverse, #ffffff));\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n margin: 0 var(--hx-space-2, 0.5rem);\n transition:\n background-color var(--hx-transition-fast, 150ms) ease,\n color var(--hx-transition-fast, 150ms) ease;\n white-space: nowrap;\n overflow: hidden;\n cursor: pointer;\n font-family: var(--hx-nav-item-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-normal, 1.5);\n position: relative;\n border: none;\n background: transparent;\n width: calc(100% - var(--hx-space-4, 1rem));\n text-align: start;\n }\n\n /* Link variant */\n a.nav-item__link {\n display: flex;\n }\n\n .nav-item__link:hover {\n background-color: var(\n --hx-nav-item-hover-bg,\n var(--hx-overlay-white-8, rgba(255, 255, 255, 0.08))\n ); /* fallback for browsers without color-mix() */\n color: var(--hx-nav-item-hover-color, var(--hx-color-text-inverse, #ffffff));\n }\n\n @supports (color: color-mix(in srgb, red 50%, blue)) {\n .nav-item__link:hover {\n background-color: var(\n --hx-nav-item-hover-bg,\n color-mix(in srgb, currentColor 10%, transparent)\n );\n }\n }\n\n .nav-item__link:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-nav-item-focus-ring-color, var(--hx-focus-ring-color, #6ab1b1));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Active State ─── */\n\n :host([active]) .nav-item__link {\n /* Active state sits on the darker primary-600 (#0F7078) fill. White text\n (#ffffff) on primary-600 = 5.39:1 WCAG AA pass. text-on-primary now\n resolves to neutral-900 (intended for the lighter primary-500 surface)\n which would fail here. text.on-primary-strong holds at neutral-0 across\n modes (no dark flip) so the active fg stays AA. 3.2.1: routed through\n the action.* / on-{role}-strong semantic tier per token-cascade\n remediation (no more bare primary-600 / neutral-0 consumption). */\n background-color: var(\n --hx-nav-item-active-bg,\n var(--hx-color-action-primary-bg-hover, #0f7078)\n );\n color: var(--hx-nav-item-active-color, var(--hx-color-text-on-primary-strong, #ffffff));\n }\n\n :host([active]) .nav-item__link:hover {\n /* text.on-primary-strong (#ffffff) on primary-700 (#0F6363) = WCAG AA ✓ */\n background-color: var(\n --hx-nav-item-active-hover-bg,\n var(--hx-color-action-primary-bg-active, #0f6363)\n );\n }\n\n /* ─── Disabled State ─── */\n\n :host([disabled]) .nav-item__link {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n cursor: not-allowed;\n }\n\n /* ─── Icon ─── */\n\n .nav-item__icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n }\n\n /* ─── Label ─── */\n\n .nav-item__label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n transition: opacity var(--hx-transition-fast, 150ms) ease;\n }\n\n /* ─── Badge ─── */\n\n .nav-item__badge {\n margin-inline-start: auto;\n flex-shrink: 0;\n }\n\n /* ─── Expand Arrow ─── */\n\n .nav-item__arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n width: var(--hx-space-5, 1.25rem);\n height: var(--hx-space-5, 1.25rem);\n transition: transform var(--hx-transition-normal, 300ms) ease;\n }\n\n .nav-item__arrow svg {\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n fill: currentColor;\n }\n\n :host([expanded]) .nav-item__arrow {\n transform: rotate(90deg);\n }\n\n /* ─── Children (sub-nav) ─── */\n\n .nav-item__children {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--hx-transition-normal, 300ms ease);\n overflow: hidden;\n }\n\n :host([expanded]) .nav-item__children {\n grid-template-rows: 1fr;\n }\n\n .nav-item__children-inner {\n overflow: hidden;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding-inline-start: var(--hx-space-6, 1.5rem);\n }\n\n /* ─── Tooltip (collapsed mode) ─── */\n\n .nav-item__tooltip {\n position: absolute;\n left: calc(100% + var(--hx-space-2, 0.5rem));\n top: 50%;\n transform: translateY(-50%);\n /* tooltip is an inverted surface — flips per mode via surface-inverse /\n text-inverse. 3.2.1: wrapped with component-tier slots so consumers can\n theme tooltip surface/text without overriding the global semantics. */\n background-color: var(--hx-nav-item-tooltip-bg, var(--hx-color-surface-inverse, #0d1825));\n color: var(--hx-nav-item-tooltip-color, var(--hx-color-text-inverse, #ffffff));\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n font-size: var(--hx-font-size-xs, 0.75rem);\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms) ease;\n z-index: var(--hx-z-index-tooltip, 1600);\n box-shadow: var(--hx-shadow-md, 0 2px 8px rgb(0 0 0 / 0.2));\n }\n\n :host([data-collapsed]) .nav-item__link:hover .nav-item__tooltip,\n :host([data-collapsed]) .nav-item__link:focus-visible .nav-item__tooltip {\n opacity: 1;\n }\n\n /* ─── Collapsed host state (propagated from parent) ─── */\n\n :host([data-collapsed]) .nav-item__label {\n width: 0;\n overflow: hidden;\n opacity: 0;\n }\n\n :host([data-collapsed]) .nav-item__badge {\n display: none;\n }\n\n :host([data-collapsed]) .nav-item__arrow {\n display: none;\n }\n\n :host([data-collapsed]) .nav-item__children {\n display: none !important;\n }\n\n :host([data-collapsed]) .nav-item__link {\n justify-content: center;\n margin: 0 var(--hx-space-1, 0.25rem);\n width: calc(100% - var(--hx-space-2, 0.5rem));\n padding: var(--hx-space-2, 0.5rem);\n position: relative;\n overflow: visible;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .nav-item__link,\n .nav-item__label,\n .nav-item__arrow,\n .nav-item__children,\n .nav-item__tooltip {\n transition: none;\n }\n\n :host([expanded]) .nav-item__children {\n grid-template-rows: 1fr;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n /*\n * Bespoke block — sole owner of forced-colors deference for hx-nav-item\n * (the forcedColorsInteractive mixin is intentionally NOT composed; XOR\n * rule in styles/forced-colors.ts). Mirrors the mixin's interactive\n * contract (ButtonFace / ButtonText / Highlight on hover, GrayText on\n * disabled) for the .nav-item__link interactive surface, then layers the\n * component-specific active-state border and tooltip border on top.\n */\n .nav-item__link {\n forced-color-adjust: none;\n background-color: ButtonFace;\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n\n .nav-item__link:hover {\n background-color: Highlight;\n color: HighlightText;\n border-color: Highlight;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n\n :host([disabled]) .nav-item__link {\n color: GrayText;\n border-color: GrayText;\n }\n\n :host([active]) .nav-item__link {\n border-color: Highlight;\n }\n\n .nav-item__link:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n .nav-item__tooltip {\n border: 1px solid CanvasText;\n }\n }\n`;\n","import { html, nothing } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixNavItemStyles } from './hx-nav-item.styles.js';\n\nconst _nextNavItemId = createIdCounter('hx-nav-item');\n\n/**\n * A navigation item for use inside hx-side-nav.\n * Supports icons, badges, sub-navigation, and active/disabled states.\n *\n * @summary Navigation item for hx-side-nav with support for icons, badges, and nested children.\n *\n * @tag hx-nav-item\n *\n * @slot - Default slot for item label text.\n * @slot icon - Icon to display before the label.\n * @slot badge - Badge content (e.g., notification count).\n * @slot children - Nested hx-nav-item children for sub-navigation.\n *\n * @csspart link - The anchor or button element.\n * @csspart icon - The icon container.\n * @csspart label - The label container.\n * @csspart badge - The badge container.\n * @csspart children - The children container.\n *\n * @cssprop [--hx-nav-item-color=var(--hx-color-text-inverse)] - Item text color.\n * @cssprop [--hx-nav-item-hover-bg] - Item hover background.\n * @cssprop [--hx-nav-item-hover-color=var(--hx-color-text-inverse)] - Item hover text color.\n * @cssprop [--hx-nav-item-active-bg=var(--hx-color-action-primary-bg-hover)] - Active item background.\n * @cssprop [--hx-nav-item-active-color=var(--hx-color-text-on-primary-strong)] - Active item text color.\n * @cssprop [--hx-nav-item-padding] - Item padding.\n * @cssprop [--hx-nav-item-host-bg=var(--hx-color-surface-inverse)] - Component host background color.\n * @cssprop [--hx-nav-item-tooltip-bg=var(--hx-color-surface-inverse)] - Tooltip background color (collapsed-rail tooltip).\n * @cssprop [--hx-nav-item-tooltip-color=var(--hx-color-text-inverse)] - Tooltip text color (collapsed-rail tooltip).\n */\n@customElement('hx-nav-item')\nexport class HelixNavItem extends HelixElement {\n // 3.2.1: forced-colors deference is owned by the bespoke @media block in\n // hx-nav-item.styles.ts (active border, focus outline, tooltip border).\n // Do NOT also compose forcedColorsInteractive — XOR rule per the mixin\n // docstring.\n static override styles = [helixNavItemStyles];\n\n /** @internal — per-instance tooltip ID */\n private _tooltipId = `${_nextNavItemId()}-tooltip`;\n\n // ─── Properties ───\n\n /**\n * The URL this nav item links to.\n * @attr href\n */\n @property({ type: String })\n href = '';\n\n /**\n * Whether this item is the current/active page.\n * @attr active\n */\n @property({ type: Boolean, reflect: true })\n active = false;\n\n /**\n * Whether the sub-navigation is expanded.\n * @attr expanded\n */\n @property({ type: Boolean, reflect: true })\n expanded = false;\n\n /**\n * Whether this nav item is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── State ───\n\n /** Whether the children slot has assigned nodes. Updated via slotchange. */\n /** @internal */\n @state() private _hasChildren = false;\n\n /** Whether this item is in collapsed mode. Set externally by hx-side-nav via data-collapsed attribute. */\n /** @internal */\n @state() private _isCollapsed = false;\n\n // ─── Attribute Observer ───\n\n static override get observedAttributes(): string[] {\n return [...super.observedAttributes, 'data-collapsed'];\n }\n\n override attributeChangedCallback(name: string, old: string | null, value: string | null): void {\n super.attributeChangedCallback(name, old, value);\n if (name === 'data-collapsed') {\n this._isCollapsed = value !== null;\n }\n }\n\n // ─── Public API ───\n\n /**\n * Delegates focus to the internal link or button element (part=\"link\").\n * Allows parent components to focus nav items without piercing the Shadow DOM.\n * WCAG 2.1.1: keyboard navigation must not cross shadow boundaries via\n * direct shadowRoot queries.\n */\n override focus(options?: FocusOptions): void {\n const inner = this.shadowRoot?.querySelector<HTMLElement>('[part=\"link\"]');\n if (inner) {\n inner.focus(options);\n } else {\n super.focus(options);\n }\n }\n\n // ─── Slot Change Handler ───\n\n /** @internal */\n private _onChildrenSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasChildren = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Private Helpers ───\n\n /** @internal */\n private _getDirectText(): string {\n return Array.from(this.childNodes)\n .filter((n) => n.nodeType === Node.TEXT_NODE)\n .map((n) => n.textContent?.trim() ?? '')\n .filter(Boolean)\n .join(' ');\n }\n\n /** @internal */\n private _handleToggle(e: Event): void {\n if (this.disabled) return;\n e.preventDefault();\n this.expanded = !this.expanded;\n }\n\n /** @internal */\n private _renderExpandArrow() {\n return html`<span class=\"nav-item__arrow\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 20 20\">\n <path\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n />\n </svg>\n </span>`;\n }\n\n // ─── Render ───\n\n override render() {\n const label = this._getDirectText();\n\n const innerContent = html`\n <span part=\"icon\" class=\"nav-item__icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"nav-item__label\">\n <slot></slot>\n </span>\n <span part=\"badge\" class=\"nav-item__badge\">\n <slot name=\"badge\"></slot>\n </span>\n ${this._hasChildren ? this._renderExpandArrow() : nothing}\n ${this._isCollapsed\n ? html`<span id=${this._tooltipId} class=\"nav-item__tooltip\" role=\"tooltip\">${label}</span>`\n : nothing}\n `;\n\n // Render as anchor when href provided and no expandable children\n const linkEl =\n this.href && !this._hasChildren\n ? html`<a\n part=\"link\"\n class=\"nav-item__link\"\n href=${this.href}\n aria-current=${this.active ? 'page' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-describedby=${this._isCollapsed ? this._tooltipId : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n >\n ${innerContent}\n </a>`\n : html`<button\n part=\"link\"\n class=\"nav-item__link\"\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-expanded=${this._hasChildren ? String(this.expanded) : nothing}\n aria-describedby=${this._isCollapsed ? this._tooltipId : nothing}\n tabindex=${this.disabled ? '-1' : '0'}\n @click=${this._handleToggle}\n >\n ${innerContent}\n </button>`;\n\n return html`\n <div class=\"nav-item\">\n ${linkEl}\n <div part=\"children\" class=\"nav-item__children\" role=\"group\">\n <div class=\"nav-item__children-inner\">\n <slot name=\"children\" @slotchange=${this._onChildrenSlotChange}></slot>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-nav-item': HelixNavItem;\n }\n}\n\nexport type { HelixNavItem as HxNavItem };\n"],"names":["helixSideNavStyles","css","HelixSideNav","HelixElement","changedProperties","slot","_a","navItems","el","item","topLevelItems","childrenSlot","_b","childItems","activeEl","currentIndex","i","_c","currentItem","_d","firstChild","parentNavItem","_e","nextIndex","targetItem","html","__decorateClass","property","customElement","helixNavItemStyles","_nextNavItemId","createIdCounter","HelixNavItem","name","old","value","options","inner","n","label","innerContent","nothing","linkEl","state"],"mappings":";;;;AAEO,MAAMA,IAAqBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACuD3B,IAAMC,IAAN,cAA2BC,EAAa;AAAA,EAAxC,cAAA;AAAA,UAAA,GAAA,SAAA,GAaL,KAAA,YAAY,IAOZ,KAAA,QAAQ;AAAA,EAAA;AAAA;AAAA,EAIC,QAAQC,GAA+C;AAC9D,UAAM,QAAQA,CAAiB,GAC3BA,EAAkB,IAAI,WAAW,KACnC,KAAK,8BAAA;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,gCAAsC;;AAC5C,UAAMC,KAAOC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAA+B;AAC7D,QAAI,CAACD,EAAM;AAEX,UAAME,IAAWF,EACd,iBAAiB,EAAE,SAAS,GAAA,CAAM,EAClC,OAAO,CAACG,MAAOA,EAAG,QAAQ,YAAA,MAAkB,aAAa;AAE5D,eAAWC,KAAQF;AACjB,MAAME,aAAgB,gBAClB,KAAK,YACPA,EAAK,aAAa,kBAAkB,EAAE,IAEtCA,EAAK,gBAAgB,gBAAgB;AAAA,EAG3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,uBAA6B;AACnC,SAAK,8BAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,eAAe,GAAwB;;AAE7C,QAAI,CADc,CAAC,aAAa,WAAW,cAAc,aAAa,QAAQ,KAAK,EACpE,SAAS,EAAE,GAAG,EAAG;AAEhC,UAAMJ,KAAOC,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAA+B;AAC7D,QAAI,CAACD,EAAM;AAEX,UAAMK,IAAgBL,EACnB,iBAAiB,EAAE,SAAS,GAAA,CAAM,EAClC;AAAA,MACC,CAACG,MACCA,EAAG,QAAQ,YAAA,MAAkB,iBAAiB,CAACA,EAAG,aAAa,UAAU;AAAA,IAAA;AAG/E,QAAIE,EAAc,WAAW,EAAG;AAIhC,UAAMH,IAA0B,CAAA;AAChC,eAAWE,KAAQC;AAGjB,UAFAH,EAAS,KAAKE,CAAI,GAEdA,EAAK,aAAa,UAAU,GAAG;AACjC,cAAME,KACJC,IAAAH,EAAK,eAAL,gBAAAG,EAAiB,cAA+B;AAClD,YAAID,GAAc;AAChB,gBAAME,IAAaF,EAChB,iBAAiB,EAAE,SAAS,GAAA,CAAM,EAClC;AAAA,YACC,CAACH,MACCA,EAAG,QAAQ,YAAA,MAAkB,iBAAiB,CAACA,EAAG,aAAa,UAAU;AAAA,UAAA;AAE/E,UAAAD,EAAS,KAAK,GAAGM,CAAU;AAAA,QAC7B;AAAA,MACF;AAGF,QAAIN,EAAS,WAAW,EAAG;AAG3B,UAAMO,IAAW,SAAS;AAC1B,QAAIC,IAAe;AACnB,aAASC,IAAI,GAAGA,IAAIT,EAAS,QAAQS,KAAK;AACxC,YAAMP,IAAOF,EAASS,CAAC;AACvB,UAAKP,MAEHA,MAASK,KACTL,EAAK,SAASK,CAAQ,OACtBG,IAAAR,EAAK,eAAL,gBAAAQ,EAAiB,SAASH,QAAc,KACxC;AACA,QAAAC,IAAeC;AACf;AAAA,MACF;AAAA,IACF;AAGA,QAAI,EAAE,QAAQ,gBAAgB,EAAE,QAAQ,aAAa;AACnD,QAAE,eAAA;AACF,YAAME,IAAcH,KAAgB,IAAIR,EAASQ,CAAY,IAAI;AACjE,UAAI,CAACG,EAAa;AAElB,UAAI,EAAE,QAAQ;AAEZ,YACEA,EAAY,aAAa,UAAU,MAAM,MACzCA,EAAY,cAAc,mBAAmB;AAE7C,UAAAA,EAAY,aAAa,YAAY,EAAE,GACtCA,EAAqD,WAAW;AAAA,iBACxDA,EAAY,aAAa,UAAU,GAAG;AAE/C,gBAAMP,KACJQ,IAAAD,EAAY,eAAZ,gBAAAC,EAAwB,cAA+B;AACzD,cAAIR,GAAc;AAChB,kBAAMS,IAAaT,EAChB,iBAAiB,EAAE,SAAS,GAAA,CAAM,EAClC;AAAA,cACC,CAACH,MACCA,EAAG,QAAQ,YAAA,MAAkB,iBAAiB,CAACA,EAAG,aAAa,UAAU;AAAA,YAAA;AAE/E,gBAAIY,GAAY;AACd,cAAAA,EAAW,MAAA;AACX;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,iBAGIF,EAAY,aAAa,UAAU;AACrC,QAAAA,EAAY,gBAAgB,UAAU,GACrCA,EAAqD,WAAW;AAAA,WAC5D;AAEL,cAAMG,IACJH,EAAY,QAAqB,yBAAyB,OAC1DI,IAAAJ,EAAY,kBAAZ,gBAAAI,EAA2B,QAAqB,mBAChD;AACF,QAAID,KAAiB,CAACA,EAAc,aAAa,UAAU,KACzDA,EAAc,MAAA;AAAA,MAElB;AAEF;AAAA,IACF;AAEA,MAAE,eAAA;AAEF,QAAIE;AACJ,IAAI,EAAE,QAAQ,cACZA,IAAYR,IAAeR,EAAS,SAAS,IAAIQ,IAAe,IAAI,IAC3D,EAAE,QAAQ,YACnBQ,IAAYR,IAAe,IAAIA,IAAe,IAAIR,EAAS,SAAS,IAC3D,EAAE,QAAQ,SACnBgB,IAAY,IAEZA,IAAYhB,EAAS,SAAS;AAGhC,UAAMiB,IAAajB,EAASgB,CAAS;AACrC,IAAKC,KAILA,EAAW,MAAA;AAAA,EACb;AAAA;AAAA;AAAA,EAKQ,gBAAsB;AAC5B,SAAK,YAAY,CAAC,KAAK,WAEnB,KAAK,YAKP,KAAK;AAAA,MACH,IAAI,YAAoC,eAAe;AAAA,QACrD,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,WAAW,GAAA;AAAA,MAAK,CAC3B;AAAA,IAAA,IAOH,KAAK;AAAA,MACH,IAAI,YAAoC,aAAa;AAAA,QACnD,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,WAAW,GAAA;AAAA,MAAM,CAC5B;AAAA,IAAA;AAAA,EAGP;AAAA;AAAA;AAAA,EAKQ,oBAAoB;AAC1B,WAAOC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA,EAES,SAAS;AAChB,WAAOA;AAAA,oDACyC,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMrC,KAAK,YAAY,sBAAsB,qBAAqB;AAAA,4BACzD,CAAC,KAAK,SAAS;AAAA,qBACtB,KAAK,aAAa;AAAA;AAAA,cAEzB,KAAK,mBAAmB;AAAA;AAAA;AAAA;AAAA,8EAIwC,KAAK,cAAc;AAAA,8BACnE,KAAK,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrD;AACF;AA/QavB,EAIK,SAAS,CAACF,CAAkB;AAS5C0B,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAZ/BzB,EAaX,WAAA,aAAA,CAAA;AAOAwB,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnBfzB,EAoBX,WAAA,SAAA,CAAA;AApBWA,IAANwB,EAAA;AAAA,EADNE,EAAc,aAAa;AAAA,GACf1B,CAAA;ACvDN,MAAM2B,IAAqB5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACIlC,MAAM6B,IAAiBC,EAAgB,aAAa;AAgC7C,IAAMC,IAAN,cAA2B7B,EAAa;AAAA,EAAxC,cAAA;AAAA,UAAA,GAAA,SAAA,GAQL,KAAQ,aAAa,GAAG2B,EAAA,CAAgB,YASxC,KAAA,OAAO,IAOP,KAAA,SAAS,IAOT,KAAA,WAAW,IAOX,KAAA,WAAW,IAMF,KAAQ,eAAe,IAIvB,KAAQ,eAAe;AAAA,EAAA;AAAA;AAAA,EAIhC,WAAoB,qBAA+B;AACjD,WAAO,CAAC,GAAG,MAAM,oBAAoB,gBAAgB;AAAA,EACvD;AAAA,EAES,yBAAyBG,GAAcC,GAAoBC,GAA4B;AAC9F,UAAM,yBAAyBF,GAAMC,GAAKC,CAAK,GAC3CF,MAAS,qBACX,KAAK,eAAeE,MAAU;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUS,MAAMC,GAA8B;;AAC3C,UAAMC,KAAQ/B,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAA2B;AAC1D,IAAI+B,IACFA,EAAM,MAAMD,CAAO,IAEnB,MAAM,MAAMA,CAAO;AAAA,EAEvB;AAAA;AAAA;AAAA,EAKQ,sBAAsB,GAAgB;AAC5C,UAAM/B,IAAO,EAAE;AACf,SAAK,eAAeA,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS;AAAA,EACrE;AAAA;AAAA;AAAA,EAKQ,iBAAyB;AAC/B,WAAO,MAAM,KAAK,KAAK,UAAU,EAC9B,OAAO,CAACiC,MAAMA,EAAE,aAAa,KAAK,SAAS,EAC3C,IAAI,CAACA,MAAA;;AAAM,eAAAhC,IAAAgC,EAAE,gBAAF,gBAAAhC,EAAe,WAAU;AAAA,KAAE,EACtC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,EACb;AAAA;AAAA,EAGQ,cAAc,GAAgB;AACpC,IAAI,KAAK,aACT,EAAE,eAAA,GACF,KAAK,WAAW,CAAC,KAAK;AAAA,EACxB;AAAA;AAAA,EAGQ,qBAAqB;AAC3B,WAAOmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT;AAAA;AAAA,EAIS,SAAS;AAChB,UAAMc,IAAQ,KAAK,eAAA,GAEbC,IAAef;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAUjB,KAAK,eAAe,KAAK,mBAAA,IAAuBgB,CAAO;AAAA,QACvD,KAAK,eACHhB,aAAgB,KAAK,UAAU,6CAA6Cc,CAAK,YACjFE,CAAO;AAAA,OAIPC,IACJ,KAAK,QAAQ,CAAC,KAAK,eACfjB;AAAA;AAAA;AAAA,mBAGS,KAAK,IAAI;AAAA,2BACD,KAAK,SAAS,SAASgB,CAAO;AAAA,4BAC7B,KAAK,WAAW,SAASA,CAAO;AAAA,+BAC7B,KAAK,eAAe,KAAK,aAAaA,CAAO;AAAA,uBACrD,KAAK,WAAW,OAAO,GAAG;AAAA;AAAA,cAEnCD,CAAY;AAAA,kBAEhBf;AAAA;AAAA;AAAA,4BAGkB,KAAK,WAAW,SAASgB,CAAO;AAAA,4BAChC,KAAK,eAAe,OAAO,KAAK,QAAQ,IAAIA,CAAO;AAAA,+BAChD,KAAK,eAAe,KAAK,aAAaA,CAAO;AAAA,uBACrD,KAAK,WAAW,OAAO,GAAG;AAAA,qBAC5B,KAAK,aAAa;AAAA;AAAA,cAEzBD,CAAY;AAAA;AAGtB,WAAOf;AAAA;AAAA,UAEDiB,CAAM;AAAA;AAAA;AAAA,gDAGgC,KAAK,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxE;AACF;AA/KaV,EAKK,SAAS,CAACH,CAAkB;AAY5CH,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAhBfK,EAiBX,WAAA,QAAA,CAAA;AAOAN,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GAvB/BK,EAwBX,WAAA,UAAA,CAAA;AAOAN,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GA9B/BK,EA+BX,WAAA,YAAA,CAAA;AAOAN,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,SAAS,SAAS,IAAM;AAAA,GArC/BK,EAsCX,WAAA,YAAA,CAAA;AAMiBN,EAAA;AAAA,EAAhBiB,EAAA;AAAM,GA5CIX,EA4CM,WAAA,gBAAA,CAAA;AAIAN,EAAA;AAAA,EAAhBiB,EAAA;AAAM,GAhDIX,EAgDM,WAAA,gBAAA,CAAA;AAhDNA,IAANN,EAAA;AAAA,EADNE,EAAc,aAAa;AAAA,GACfI,CAAA;"}
|
package/figma-inventory.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-04-
|
|
3
|
+
"generatedAt": "2026-04-25T20:02:01.523Z",
|
|
4
4
|
"sourceCem": "custom-elements.json",
|
|
5
5
|
"helixVersion": "3.2.0",
|
|
6
6
|
"tokensVersion": "3.2.0",
|
|
@@ -13658,12 +13658,12 @@
|
|
|
13658
13658
|
{
|
|
13659
13659
|
"description": "Item text color.",
|
|
13660
13660
|
"name": "--hx-nav-item-color",
|
|
13661
|
-
"default": "var(--hx-color-
|
|
13661
|
+
"default": "var(--hx-color-text-inverse)",
|
|
13662
13662
|
"figmaBinding": {
|
|
13663
13663
|
"target": "Fill",
|
|
13664
13664
|
"layerSelector": "root",
|
|
13665
|
-
"semanticToken": "color/
|
|
13666
|
-
"fallbackPrimitive":
|
|
13665
|
+
"semanticToken": "color/text/inverse",
|
|
13666
|
+
"fallbackPrimitive": null,
|
|
13667
13667
|
"literalFallback": null
|
|
13668
13668
|
}
|
|
13669
13669
|
},
|
|
@@ -13675,36 +13675,36 @@
|
|
|
13675
13675
|
{
|
|
13676
13676
|
"description": "Item hover text color.",
|
|
13677
13677
|
"name": "--hx-nav-item-hover-color",
|
|
13678
|
-
"default": "var(--hx-color-
|
|
13678
|
+
"default": "var(--hx-color-text-inverse)",
|
|
13679
13679
|
"figmaBinding": {
|
|
13680
13680
|
"target": "Fill",
|
|
13681
13681
|
"layerSelector": "root",
|
|
13682
|
-
"semanticToken": "color/
|
|
13683
|
-
"fallbackPrimitive":
|
|
13682
|
+
"semanticToken": "color/text/inverse",
|
|
13683
|
+
"fallbackPrimitive": null,
|
|
13684
13684
|
"literalFallback": null
|
|
13685
13685
|
}
|
|
13686
13686
|
},
|
|
13687
13687
|
{
|
|
13688
13688
|
"description": "Active item background.",
|
|
13689
13689
|
"name": "--hx-nav-item-active-bg",
|
|
13690
|
-
"default": "var(--hx-color-primary-
|
|
13690
|
+
"default": "var(--hx-color-action-primary-bg-hover)",
|
|
13691
13691
|
"figmaBinding": {
|
|
13692
13692
|
"target": "Fill",
|
|
13693
13693
|
"layerSelector": "root",
|
|
13694
|
-
"semanticToken": "color/primary",
|
|
13695
|
-
"fallbackPrimitive":
|
|
13694
|
+
"semanticToken": "color/action/primary/bg/hover",
|
|
13695
|
+
"fallbackPrimitive": null,
|
|
13696
13696
|
"literalFallback": null
|
|
13697
13697
|
}
|
|
13698
13698
|
},
|
|
13699
13699
|
{
|
|
13700
13700
|
"description": "Active item text color.",
|
|
13701
13701
|
"name": "--hx-nav-item-active-color",
|
|
13702
|
-
"default": "var(--hx-color-
|
|
13702
|
+
"default": "var(--hx-color-text-on-primary-strong)",
|
|
13703
13703
|
"figmaBinding": {
|
|
13704
13704
|
"target": "Fill",
|
|
13705
13705
|
"layerSelector": "root",
|
|
13706
|
-
"semanticToken": "color/
|
|
13707
|
-
"fallbackPrimitive":
|
|
13706
|
+
"semanticToken": "color/text/on/primary/strong",
|
|
13707
|
+
"fallbackPrimitive": null,
|
|
13708
13708
|
"literalFallback": null
|
|
13709
13709
|
}
|
|
13710
13710
|
},
|
|
@@ -13716,12 +13716,36 @@
|
|
|
13716
13716
|
{
|
|
13717
13717
|
"description": "Component host background color.",
|
|
13718
13718
|
"name": "--hx-nav-item-host-bg",
|
|
13719
|
-
"default": "var(--hx-color-
|
|
13719
|
+
"default": "var(--hx-color-surface-inverse)",
|
|
13720
13720
|
"figmaBinding": {
|
|
13721
13721
|
"target": "Fill",
|
|
13722
13722
|
"layerSelector": "root",
|
|
13723
|
-
"semanticToken": "color/
|
|
13724
|
-
"fallbackPrimitive":
|
|
13723
|
+
"semanticToken": "color/surface/inverse",
|
|
13724
|
+
"fallbackPrimitive": null,
|
|
13725
|
+
"literalFallback": null
|
|
13726
|
+
}
|
|
13727
|
+
},
|
|
13728
|
+
{
|
|
13729
|
+
"description": "Tooltip background color (collapsed-rail tooltip).",
|
|
13730
|
+
"name": "--hx-nav-item-tooltip-bg",
|
|
13731
|
+
"default": "var(--hx-color-surface-inverse)",
|
|
13732
|
+
"figmaBinding": {
|
|
13733
|
+
"target": "Fill",
|
|
13734
|
+
"layerSelector": "root",
|
|
13735
|
+
"semanticToken": "color/surface/inverse",
|
|
13736
|
+
"fallbackPrimitive": null,
|
|
13737
|
+
"literalFallback": null
|
|
13738
|
+
}
|
|
13739
|
+
},
|
|
13740
|
+
{
|
|
13741
|
+
"description": "Tooltip text color (collapsed-rail tooltip).",
|
|
13742
|
+
"name": "--hx-nav-item-tooltip-color",
|
|
13743
|
+
"default": "var(--hx-color-text-inverse)",
|
|
13744
|
+
"figmaBinding": {
|
|
13745
|
+
"target": "Fill",
|
|
13746
|
+
"layerSelector": "root",
|
|
13747
|
+
"semanticToken": "color/text/inverse",
|
|
13748
|
+
"fallbackPrimitive": null,
|
|
13725
13749
|
"literalFallback": null
|
|
13726
13750
|
}
|
|
13727
13751
|
}
|
|
@@ -17626,36 +17650,36 @@
|
|
|
17626
17650
|
{
|
|
17627
17651
|
"description": "Background color.",
|
|
17628
17652
|
"name": "--hx-side-nav-bg",
|
|
17629
|
-
"default": "var(--hx-color-
|
|
17653
|
+
"default": "var(--hx-color-surface-inverse)",
|
|
17630
17654
|
"figmaBinding": {
|
|
17631
17655
|
"target": "Fill",
|
|
17632
17656
|
"layerSelector": "root",
|
|
17633
|
-
"semanticToken": "color/
|
|
17634
|
-
"fallbackPrimitive":
|
|
17657
|
+
"semanticToken": "color/surface/inverse",
|
|
17658
|
+
"fallbackPrimitive": null,
|
|
17635
17659
|
"literalFallback": null
|
|
17636
17660
|
}
|
|
17637
17661
|
},
|
|
17638
17662
|
{
|
|
17639
17663
|
"description": "Text color.",
|
|
17640
17664
|
"name": "--hx-side-nav-color",
|
|
17641
|
-
"default": "var(--hx-color-
|
|
17665
|
+
"default": "var(--hx-color-text-inverse)",
|
|
17642
17666
|
"figmaBinding": {
|
|
17643
17667
|
"target": "Fill",
|
|
17644
17668
|
"layerSelector": "root",
|
|
17645
|
-
"semanticToken": "color/
|
|
17646
|
-
"fallbackPrimitive":
|
|
17669
|
+
"semanticToken": "color/text/inverse",
|
|
17670
|
+
"fallbackPrimitive": null,
|
|
17647
17671
|
"literalFallback": null
|
|
17648
17672
|
}
|
|
17649
17673
|
},
|
|
17650
17674
|
{
|
|
17651
17675
|
"description": "Border color.",
|
|
17652
17676
|
"name": "--hx-side-nav-border-color",
|
|
17653
|
-
"default": "var(--hx-color-
|
|
17677
|
+
"default": "var(--hx-color-border-strong)",
|
|
17654
17678
|
"figmaBinding": {
|
|
17655
17679
|
"target": "Stroke",
|
|
17656
17680
|
"layerSelector": "root",
|
|
17657
|
-
"semanticToken": "color/
|
|
17658
|
-
"fallbackPrimitive":
|
|
17681
|
+
"semanticToken": "color/border/strong",
|
|
17682
|
+
"fallbackPrimitive": null,
|
|
17659
17683
|
"literalFallback": null
|
|
17660
17684
|
}
|
|
17661
17685
|
},
|
|
@@ -17684,14 +17708,26 @@
|
|
|
17684
17708
|
}
|
|
17685
17709
|
},
|
|
17686
17710
|
{
|
|
17687
|
-
"description": "Toggle button icon color.",
|
|
17711
|
+
"description": "Toggle button icon color (resting).",
|
|
17688
17712
|
"name": "--hx-side-nav-toggle-color",
|
|
17689
|
-
"default": "var(--hx-color-
|
|
17713
|
+
"default": "var(--hx-color-text-inverse)",
|
|
17690
17714
|
"figmaBinding": {
|
|
17691
17715
|
"target": "Fill",
|
|
17692
17716
|
"layerSelector": "::part(toggle)",
|
|
17693
|
-
"semanticToken": "color/
|
|
17694
|
-
"fallbackPrimitive":
|
|
17717
|
+
"semanticToken": "color/text/inverse",
|
|
17718
|
+
"fallbackPrimitive": null,
|
|
17719
|
+
"literalFallback": null
|
|
17720
|
+
}
|
|
17721
|
+
},
|
|
17722
|
+
{
|
|
17723
|
+
"description": "Toggle button icon color on hover.",
|
|
17724
|
+
"name": "--hx-side-nav-toggle-hover-color",
|
|
17725
|
+
"default": "var(--hx-color-text-inverse)",
|
|
17726
|
+
"figmaBinding": {
|
|
17727
|
+
"target": "Fill",
|
|
17728
|
+
"layerSelector": "root",
|
|
17729
|
+
"semanticToken": "color/text/inverse",
|
|
17730
|
+
"fallbackPrimitive": null,
|
|
17695
17731
|
"literalFallback": null
|
|
17696
17732
|
}
|
|
17697
17733
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helixui/library",
|
|
3
|
-
"version": "3.2.0-next.
|
|
3
|
+
"version": "3.2.0-next.81",
|
|
4
4
|
"description": "Enterprise Web Component Library built with Lit 3.x",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"customElements": "custom-elements.json",
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"lit": "^3.3.2",
|
|
62
|
-
"@helixui/tokens": "3.2.0-next.
|
|
62
|
+
"@helixui/tokens": "3.2.0-next.81"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@floating-ui/dom": "^1.7.6"
|