@nysds/nys-tab 1.18.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nys-tab.js +13 -10
- package/dist/nys-tab.js.map +1 -1
- package/dist/nys-tabgroup.d.ts +1 -0
- package/package.json +2 -2
package/dist/nys-tab.js
CHANGED
|
@@ -10,7 +10,7 @@ import { property as h } from "lit/decorators.js";
|
|
|
10
10
|
* Repository: https://github.com/its-hcd/nysds
|
|
11
11
|
* License: MIT
|
|
12
12
|
*/
|
|
13
|
-
const w = ':host{--_nys-tabgroup-gap: var(--nys-space-100, 8px);--_nys-tabgroup-padding: var(--nys-space-50, 4px);--_nys-tabgroup-background-color: var(--nys-color-surface, #ffffff);--_nys-tab-border-width: 3px;--_nys-tab-border-radius: var(--nys-radius-md, 4px);--_nys-tab-border-color: var(--nys-color-neutral-50);--_nys-tab-border-color--hover: var(--nys-color-theme-weak, #cddde9);--_nys-tab-border-color--active: var(--nys-color-theme-mid, #457aa5);--_nys-tab-border-color--disabled: var(--_nys-tab-border-color);--_nys-tab-border-color--selected: var(--nys-color-theme, #154973);--_nys-tab-border-color--selected--hover: var( --nys-color-theme-strong, #0e324f );--_nys-tab-border-color--selected--active: var( --nys-color-theme-stronger, #081b2b );--_nys-tab-background-color: var(--nys-color-surface, #ffffff);--_nys-tab-background-color--hover: var(--nys-color-theme-weaker, #eff6fb);--_nys-tab-background-color--active: var(--nys-color-theme-weak, #cddde9);--_nys-tab-background-color--disabled: var(--_nys-tab-background-color);--_nys-tab-background-color--selected: var(--nys-color-neutral-10, #f6f6f6);--_nys-tab-color: var(--nys-color-text-weak, #
|
|
13
|
+
const w = ':host{--_nys-tabgroup-gap: var(--nys-space-100, 8px);--_nys-tabgroup-padding: var(--nys-space-50, 4px);--_nys-tabgroup-background-color: var(--nys-color-surface, #ffffff);--_nys-tab-border-width: 3px;--_nys-tab-border-radius: var(--nys-radius-md, 4px);--_nys-tab-border-color: var(--nys-color-neutral-50);--_nys-tab-border-color--hover: var(--nys-color-theme-weak, #cddde9);--_nys-tab-border-color--active: var(--nys-color-theme-mid, #457aa5);--_nys-tab-border-color--disabled: var(--_nys-tab-border-color);--_nys-tab-border-color--selected: var(--nys-color-theme, #154973);--_nys-tab-border-color--selected--hover: var( --nys-color-theme-strong, #0e324f );--_nys-tab-border-color--selected--active: var( --nys-color-theme-stronger, #081b2b );--_nys-tab-background-color: var(--nys-color-surface, #ffffff);--_nys-tab-background-color--hover: var(--nys-color-theme-weaker, #eff6fb);--_nys-tab-background-color--active: var(--nys-color-theme-weak, #cddde9);--_nys-tab-background-color--disabled: var(--_nys-tab-background-color);--_nys-tab-background-color--selected: var(--nys-color-neutral-10, #f6f6f6);--_nys-tab-color: var(--nys-color-text-weak, #4a4d4f);--_nys-tab-color--selected: var(--nys-color-text, #1b1b1b);--_nys-tab-color--disabled: var(--nys-color-text-disabled, #bec0c1);--_nys-tab-padding--x: var(--nys-space-150, 12px);--_nys-tab-padding--y: var(--nys-space-200, 16px);--_nys-tabpanel-padding: var(--nys-space-400, 32px);--_nys-tabpanel-max-height: var(--nys-tabpanel-max-height)}.nys-tab{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;cursor:pointer;appearance:none;-webkit-appearance:none;padding:var(--_nys-tab-padding--y) var(--_nys-tab-padding--x);border-color:var(--_nys-tab-border-color);border-style:none none solid;border-width:var(--_nys-tab-border-width);border-radius:var(--_nys-tab-border-radius) var(--_nys-tab-border-radius) 0 0;background-color:var(--_nys-tab-background-color);color:var(--_nys-tab-color);font-family:var(--nys-font-family-ui, var(--nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif));font-size:var(--nys-font-size-ui-md, 16px);font-weight:var(--nys-font-weight-semibold, 600);line-height:var(--nys-size-200, 16px);text-decoration:none}:host(:not([disabled])) .nys-tab:hover{background-color:var(--_nys-tab-background-color--hover);border-color:var(--_nys-tab-border-color--hover);color:var(--_nys-tab-color)}:host(:not([disabled])) .nys-tab:active{background-color:var(--_nys-tab-background-color--active);border-color:var(--_nys-tab-border-color--active);color:var(--_nys-tab-color)}:host([disabled]) .nys-tab{background-color:var(--_nys-tab-background-color--disabled);border-color:var(--_nys-tab-border-color--disabled);color:var(--_nys-tab-color--disabled);cursor:not-allowed;pointer-events:auto}:host(:focus-visible){outline:none}:host(:focus-visible) .nys-tab{outline:solid var(--nys-border-width-md, 2px) var(--nys-color-focus, #004dd1);outline-offset:var(--nys-space-2px, 2px)}:host([selected]) .nys-tab{background-color:var(--_nys-tab-background-color--selected);border-color:var(--_nys-tab-border-color--selected);color:var(--_nys-tab-color--selected)}:host([selected]:not([disabled])) .nys-tab:hover{border-color:var(--_nys-tab-border-color--selected--hover)}:host([selected]:not([disabled])) .nys-tab:active{border-color:var(--_nys-tab-border-color--selected--active)}.nys-tabgroup{background-color:var(--_nys-tabgroup-background-color)}.nys-tabgroup__tabs-container{position:relative}.nys-tabgroup__tabs-container .scroll-shadow{position:absolute;top:50%;transform:translateY(-50%);z-index:2;opacity:0;pointer-events:none;transition:opacity .2s;height:calc(var(--nys-space-600, 48px) + var(--_nys-tab-border-width));width:var(--nys-space-200, 16px)}.nys-tabgroup__tabs-container .scroll-shadow--left{left:0;background-image:linear-gradient(to left,transparent,var(--nys-color-neutral-100, #d0d0ce))}.nys-tabgroup__tabs-container .scroll-shadow--right{right:0;background-image:linear-gradient(to right,transparent,var(--nys-color-neutral-100, #d0d0ce))}.nys-tabgroup__tabs-container .scroll-shadow.is-visible{opacity:1}.nys-tabgroup__tabs-container .nys-tabgroup__tabs-background{position:absolute;inset:0;margin:var(--_nys-tabgroup-padding);border-bottom:solid var(--_nys-tab-border-color) var(--_nys-tab-border-width)}.nys-tabgroup__tabs-container .nys-tabgroup__tabs{position:relative;display:flex;gap:var(--_nys-tabgroup-gap);overflow-x:auto;white-space:nowrap;-ms-overflow-style:none;scrollbar-width:none;padding:var(--_nys-tabgroup-padding)}.nys-tabgroup__tabs-container .nys-tabgroup__tabs::-webkit-scrollbar{display:none}.nys-tabgroup__panels{padding:var(--_nys-tabpanel-padding);background-color:var(--_nys-tabpanel-background-color);max-height:var(--_nys-tabpanel-max-height);overflow-y:auto}';
|
|
14
14
|
var $ = Object.defineProperty, v = (i, t, r, n) => {
|
|
15
15
|
for (var e = void 0, s = i.length - 1, o; s >= 0; s--)
|
|
16
16
|
(o = i[s]) && (e = o(t, r, e) || e);
|
|
@@ -115,12 +115,12 @@ v([
|
|
|
115
115
|
h({ type: Boolean, reflect: !0 })
|
|
116
116
|
], b.prototype, "disabled");
|
|
117
117
|
customElements.get("nys-tab") || customElements.define("nys-tab", b);
|
|
118
|
-
var P = Object.defineProperty,
|
|
118
|
+
var P = Object.defineProperty, L = (i, t, r, n) => {
|
|
119
119
|
for (var e = void 0, s = i.length - 1, o; s >= 0; s--)
|
|
120
120
|
(o = i[s]) && (e = o(t, r, e) || e);
|
|
121
121
|
return e && P(t, r, e), e;
|
|
122
122
|
};
|
|
123
|
-
let
|
|
123
|
+
let z = 0;
|
|
124
124
|
const x = class x extends f {
|
|
125
125
|
constructor() {
|
|
126
126
|
super(...arguments), this.id = "", this.name = "", this._updateScrollShadows = () => {
|
|
@@ -138,7 +138,7 @@ const x = class x extends f {
|
|
|
138
138
|
* Auto-generates a unique `id` if one was not provided.
|
|
139
139
|
*/
|
|
140
140
|
connectedCallback() {
|
|
141
|
-
super.connectedCallback(), this.id || (this.id = `nys-tabgroup-${Date.now()}-${
|
|
141
|
+
super.connectedCallback(), this.id || (this.id = `nys-tabgroup-${Date.now()}-${z++}`);
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
144
|
* Called after the element's shadow DOM has been rendered for the first time.
|
|
@@ -157,6 +157,9 @@ const x = class x extends f {
|
|
|
157
157
|
() => this._updateScrollShadows()
|
|
158
158
|
), this._resizeObserver.observe(this._tabsEl);
|
|
159
159
|
}
|
|
160
|
+
disconnectedCallback() {
|
|
161
|
+
super.disconnectedCallback(), this._tabsEl?.removeEventListener("scroll", this._updateScrollShadows), this._tabsEl?.removeEventListener("wheel", this._handleWheel), this._resizeObserver?.disconnect(), this._resizeObserver = void 0;
|
|
162
|
+
}
|
|
160
163
|
/**
|
|
161
164
|
* Returns all `<nys-tab>` elements currently residing in the shadow-DOM
|
|
162
165
|
* tabs container, in DOM order.
|
|
@@ -246,8 +249,8 @@ const x = class x extends f {
|
|
|
246
249
|
}), a.forEach((l) => u.push(l)), u.forEach((l) => s.appendChild(l));
|
|
247
250
|
const C = o.findIndex(
|
|
248
251
|
(l) => l.hasAttribute("selected")
|
|
249
|
-
),
|
|
250
|
-
this._applySelection(o, u,
|
|
252
|
+
), A = C !== -1 ? C : 0;
|
|
253
|
+
this._applySelection(o, u, A);
|
|
251
254
|
}
|
|
252
255
|
/**
|
|
253
256
|
* Handles the `nys-tab-select` custom event bubbled up from a child
|
|
@@ -332,17 +335,17 @@ const x = class x extends f {
|
|
|
332
335
|
};
|
|
333
336
|
x.styles = g(w);
|
|
334
337
|
let y = x;
|
|
335
|
-
|
|
338
|
+
L([
|
|
336
339
|
h({ type: String, reflect: !0 })
|
|
337
340
|
], y.prototype, "id");
|
|
338
|
-
|
|
341
|
+
L([
|
|
339
342
|
h({ type: String })
|
|
340
343
|
], y.prototype, "name");
|
|
341
344
|
customElements.get("nys-tabgroup") || customElements.define("nys-tabgroup", y);
|
|
342
|
-
var
|
|
345
|
+
var O = Object.defineProperty, q = (i, t, r, n) => {
|
|
343
346
|
for (var e = void 0, s = i.length - 1, o; s >= 0; s--)
|
|
344
347
|
(o = i[s]) && (e = o(t, r, e) || e);
|
|
345
|
-
return e &&
|
|
348
|
+
return e && O(t, r, e), e;
|
|
346
349
|
};
|
|
347
350
|
let I = 0;
|
|
348
351
|
const E = class E extends f {
|
package/dist/nys-tab.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nys-tab.js","sources":["../src/nys-tab.ts","../src/nys-tabgroup.ts","../src/nys-tabpanel.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tab>` is a single tab within a `<nys-tabgroup>`.\n *\n * The host element carries `role=\"tab\"`, `tabindex`, `aria-selected`,\n * `aria-controls`, and `aria-disabled` so assistive technologies see the\n * correct ARIA tab semantics on the element that is actually focused.\n * `<nys-tabgroup>` manages `tabindex`, `aria-selected`, and `aria-controls`\n * via `_applySelection`; do not set them directly on this element.\n *\n * @element nys-tab\n *\n * @fires nys-tab-select - Dispatched when the tab is activated via click or\n * Enter / Space. Bubbles and crosses shadow DOM boundaries.\n * `detail: { id: string, label: string }`\n * @fires nys-tab-focus - Dispatched when the host receives focus. Bubbles and\n * crosses shadow DOM boundaries. `detail: { id: string }`\n * @fires nys-tab-blur - Dispatched when the host loses focus. Bubbles and\n * crosses shadow DOM boundaries. `detail: { id: string }`\n *\n * @slot - No slots; content is derived from the `label` property.\n *\n * @example `<nys-tab>` and `<nys-tabpanel>` should always be wrapped by `<nys-tabgroup>`\n * ```html\n * <!-- Always place <nys-tab> elements inside a <nys-tabgroup>. -->\n * <nys-tabgroup name=\"My Tabs\">\n * <nys-tab label=\"Overview\"></nys-tab>\n * <nys-tab label=\"Details\" selected></nys-tab>\n * <nys-tab label=\"Archived\" disabled></nys-tab>\n * <nys-tabpanel><p>Overview content</p></nys-tabpanel>\n * <nys-tabpanel><p>Details content (shown by default)</p></nys-tabpanel>\n * <nys-tabpanel><p>Archived content</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTab extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the tab element.\n * Reflected to the DOM attribute so `aria-controls` references resolve.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n /**\n * Visible text label rendered inside the inner `<span>`.\n *\n * @attr label\n */\n @property({ type: String }) label = \"\";\n\n /**\n * Whether this tab is the currently active tab.\n * Managed by `<nys-tabgroup>`; reflected for CSS attribute selectors.\n *\n * @attr selected\n */\n @property({ type: Boolean, reflect: true }) selected = false;\n\n /**\n * Whether this tab is disabled.\n * Reflected to the DOM attribute for CSS styling.\n *\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Sets `role=\"tab\"` and `tabindex=\"-1\"` on the host (the element that AT\n * will read and that receives keyboard focus). Attaches host-level listeners\n * for keydown, focus, blur, and click so that interaction events work\n * correctly on the host element itself.\n *\n * Click is handled at the host level so iOS VoiceOver double-tap (which\n * dispatches `click` directly on the host because of `role=\"tab\"`, bypassing\n * shadow-DOM children) activates the tab. Normal taps land on the inner\n * `<span>` and bubble up to this listener.\n *\n * `<nys-tabgroup>` overrides `tabindex` to `\"0\"` on the selected tab.\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tab-${Date.now()}-${componentIdCounter++}`;\n }\n this.setAttribute(\"role\", \"tab\");\n this.setAttribute(\"tabindex\", \"-1\");\n this.addEventListener(\"keydown\", this._onKeydown);\n this.addEventListener(\"focus\", this._onFocus);\n this.addEventListener(\"blur\", this._onBlur);\n this.addEventListener(\"click\", this._onClick);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"keydown\", this._onKeydown);\n this.removeEventListener(\"focus\", this._onFocus);\n this.removeEventListener(\"blur\", this._onBlur);\n this.removeEventListener(\"click\", this._onClick);\n }\n\n /**\n * Keeps `aria-disabled` on the host in sync with the `disabled` property so\n * AT perceives the disabled state on the element it actually focuses.\n */\n updated(changed: Map<string, unknown>) {\n if (changed.has(\"disabled\")) {\n if (this.disabled) {\n this.setAttribute(\"aria-disabled\", \"true\");\n } else {\n this.removeAttribute(\"aria-disabled\");\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Focuses the host element. The host carries `role=\"tab\"` and `tabindex`,\n * so it is the correct element for AT to land on.\n */\n public focus(options?: FocusOptions): void {\n super.focus(options);\n }\n\n // ---------------------------------------------------------------------------\n // Event Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Enter / Space on the focused host activate the tab.\n * Arrow-key navigation is handled one level up by `<nys-tabgroup>`.\n */\n private _onKeydown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n this._handleClick();\n };\n\n /**\n * Host focus → dispatch `nys-tab-focus` for external observers.\n */\n private _onFocus = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-focus\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id },\n }),\n );\n };\n\n /**\n * Host blur → dispatch `nys-tab-blur` for external observers.\n */\n private _onBlur = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-blur\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id },\n }),\n );\n };\n\n /**\n * Host-level click handler. Activates the tab regardless of whether the\n * click landed on the inner element (normal pointer/keyboard tap, which\n * bubbles up) or directly on the host (iOS VoiceOver double-tap dispatches\n * `click` on the element with `role=\"tab\"`, bypassing shadow-DOM children).\n */\n private _onClick = (): void => {\n this._handleClick();\n };\n\n /**\n * Focuses the host then dispatches `nys-tab-select`. Called from both the\n * click handler and the keydown handler.\n */\n private _handleClick(): void {\n if (this.disabled) return;\n this.focus();\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-select\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id, label: this.label },\n }),\n );\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n // Inner element is a non-interactive `<span>` (not `<button>`) so that\n // axe-core's `nested-interactive` rule does not fire — the host already\n // carries `role=\"tab\"` + `tabindex` and is the interactive control.\n // Disabled gating, click activation, and keyboard activation all happen\n // on the host; the span is purely a styling/labeling target.\n return html`<span class=\"nys-tab\">${this.label}</span>`;\n }\n}\n\nif (!customElements.get(\"nys-tab\")) {\n customElements.define(\"nys-tab\", NysTab);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tabgroup>` is the container for `<nys-tab>` and `<nys-tabpanel>`\n * elements.\n *\n * Accepts tabs and panels as flat light-DOM children in any order (interleaved\n * or grouped). On slot change, children are sorted into dedicated shadow-DOM\n * containers, ARIA relationships are wired, and the first selected (or first)\n * tab is activated.\n *\n * Scroll shadows are rendered on either side of the tab list and toggled via\n * `ResizeObserver` and a `scroll` listener so they accurately reflect whether\n * overflow content exists in each direction.\n *\n * Keyboard navigation follows the\n * {@link https://www.w3.org/WAI/ARIA/apg/patterns/tabs/ ARIA Tabs Pattern}:\n * - Arrow keys move focus without changing selection.\n * - Enter / Space confirm selection on the focused tab.\n *\n * @element nys-tabgroup\n *\n * @slot - Accepts `<nys-tab>` and `<nys-tabpanel>` children. Elements are\n * moved into internal shadow-DOM containers on `slotchange`; the slot\n * itself is not rendered visibly.\n *\n * @example Disable a tab using the `disabled` attribute on `<nys-tab>`.\n * ```html\n * <nys-tabgroup name=\"Account Settings\">\n * <nys-tab label=\"Profile\"></nys-tab>\n * <nys-tab label=\"Security\"></nys-tab>\n * <nys-tab label=\"Notifications\" disabled></nys-tab>\n * <nys-tabpanel><p>Manage your profile information.</p></nys-tabpanel>\n * <nys-tabpanel><p>Update your password and 2FA settings.</p></nys-tabpanel>\n * <nys-tabpanel><p>Notification preferences (coming soon).</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n *\n * @example Pre-select a tab using the `selected` attribute on `<nys-tab>`.\n * ```html\n * <nys-tabgroup name=\"Reports\">\n * <nys-tab label=\"Summary\"></nys-tab>\n * <nys-tab label=\"Details\" selected></nys-tab>\n * <nys-tabpanel><p>Summary view</p></nys-tabpanel>\n * <nys-tabpanel><p>Detailed view (shown by default)</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTabgroup extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the tabgroup element.\n * If not provided, one is auto-generated in `connectedCallback`.\n * Reflected to the DOM attribute.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n /**\n * The name of the tab group.\n * Used for form submission and accessibility purposes.\n *\n * @attr name\n */\n @property({ type: String }) name = \"\";\n\n /**\n * Cached in `firstUpdated` and used by `_updateScrollShadows` to read\n * scroll position and dimensions.\n */\n private _tabsEl!: HTMLElement;\n\n /**\n * Reference to the left scroll-shadow overlay element.\n * Receives the `is-visible` class when the tab list is scrolled away from\n * its leftmost position.\n */\n private _shadowLeft!: HTMLElement;\n\n /**\n * Reference to the right scroll-shadow overlay element.\n * Receives the `is-visible` class when overflow content exists to the right\n * of the current scroll position.\n */\n private _shadowRight!: HTMLElement;\n\n /**\n * `ResizeObserver` instance watching `_tabsEl` for size changes.\n * Re-evaluates scroll shadow visibility whenever the tab list is resized\n * (e.g. viewport resize, dynamic tab additions).\n * Stored so it can be disconnected if needed.\n */\n private _resizeObserver?: ResizeObserver;\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Called when the element is inserted into the document.\n * Auto-generates a unique `id` if one was not provided.\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tabgroup-${Date.now()}-${componentIdCounter++}`;\n }\n }\n\n /**\n * Called after the element's shadow DOM has been rendered for the first time.\n *\n * Caches references to the tab list and scroll-shadow elements, performs an\n * initial scroll-shadow evaluation, and attaches:\n * - A `scroll` event listener on `_tabsEl` to update shadows on scroll.\n * - A `ResizeObserver` on `_tabsEl` to update shadows when the container\n * is resized.\n */\n firstUpdated() {\n const root = this.shadowRoot!;\n this._tabsEl = root.querySelector(\".nys-tabgroup__tabs\")!;\n this._shadowLeft = root.querySelector(\".scroll-shadow--left\")!;\n this._shadowRight = root.querySelector(\".scroll-shadow--right\")!;\n\n this._updateScrollShadows();\n\n this._tabsEl.addEventListener(\"scroll\", this._updateScrollShadows);\n this._tabsEl.addEventListener(\"wheel\", this._handleWheel, {\n passive: false,\n });\n\n this._resizeObserver = new ResizeObserver(() =>\n this._updateScrollShadows(),\n );\n this._resizeObserver.observe(this._tabsEl);\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Reads the current scroll state of `_tabsEl` and toggles the `is-visible`\n * class on the left and right shadow overlays accordingly.\n *\n * - Left shadow is visible when `scrollLeft > 0`.\n * - Right shadow is visible when `scrollLeft + clientWidth < scrollWidth`\n * (i.e. content exists beyond the right edge).\n *\n * Defined as an arrow function so it can be passed directly as an event\n * listener without losing `this` context.\n *\n * @returns void\n */\n private _updateScrollShadows = (): void => {\n const { scrollLeft, scrollWidth, clientWidth } = this._tabsEl;\n\n const canScrollLeft = scrollLeft > 0;\n const canScrollRight = scrollLeft + clientWidth < scrollWidth;\n\n this._shadowLeft.classList.toggle(\"is-visible\", canScrollLeft);\n this._shadowRight.classList.toggle(\"is-visible\", canScrollRight);\n };\n\n /**\n * Returns all `<nys-tab>` elements currently residing in the shadow-DOM\n * tabs container, in DOM order.\n *\n * @returns An array of `HTMLElement` references to every `<nys-tab>` child.\n */\n private _getTabs(): HTMLElement[] {\n return Array.from(\n this.shadowRoot\n ?.querySelector(\".nys-tabgroup__tabs\")\n ?.querySelectorAll(\"nys-tab\") ?? [],\n ) as HTMLElement[];\n }\n\n /**\n * Returns all `<nys-tabpanel>` elements currently residing in the\n * shadow-DOM panels container, in DOM order.\n *\n * @returns An array of `HTMLElement` references to every `<nys-tabpanel>` child.\n */\n private _getPanels(): HTMLElement[] {\n return Array.from(\n this.shadowRoot\n ?.querySelector(\".nys-tabgroup__panels\")\n ?.querySelectorAll(\"nys-tabpanel\") ?? [],\n ) as HTMLElement[];\n }\n\n /**\n * Single source of truth for ARIA wiring, `tabindex`, and panel visibility.\n *\n * For each index `i`:\n * - Sets `selected` / removes `selected` attribute on `tabs[i]`.\n * - Sets `aria-controls` on `tabs[i]` to the `id` of `panels[i]`.\n * - Sets `aria-labelledby` on `panels[i]` to the `id` of `tabs[i]`.\n * - Removes `hidden` from `panels[selectedIndex]`; adds it to all others.\n *\n * Must be called any time the selected tab changes (initial render and\n * subsequent user interactions).\n *\n * @param tabs - Ordered array of `<nys-tab>` elements to update.\n * @param panels - Ordered array of `<nys-tabpanel>` elements to update.\n * Must be the same length as `tabs` for correct pairing.\n * @param selectedIndex - Zero-based index of the tab/panel pair to activate.\n * @returns void\n */\n private _applySelection(\n tabs: HTMLElement[],\n panels: HTMLElement[],\n selectedIndex: number,\n ): void {\n tabs.forEach((tab, i) => {\n const isSelected = i === selectedIndex;\n const panel = panels[i];\n tab.setAttribute(\"aria-selected\", isSelected ? \"true\" : \"false\");\n tab.setAttribute(\"tabindex\", isSelected ? \"0\" : \"-1\");\n if (panel?.id) {\n tab.setAttribute(\"aria-controls\", panel.id);\n }\n if (isSelected) {\n tab.setAttribute(\"selected\", \"\");\n } else {\n tab.removeAttribute(\"selected\");\n }\n });\n\n panels.forEach((panel, i) => {\n const isSelected = i === selectedIndex;\n const tab = tabs[i];\n if (tab) {\n panel.setAttribute(\"aria-labelledby\", tab.id);\n }\n if (isSelected) {\n panel.removeAttribute(\"hidden\");\n } else {\n panel.setAttribute(\"hidden\", \"\");\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Event Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Handles `slotchange` on the default slot.\n *\n * Iterates over all assigned elements and moves each `<nys-tab>` into\n * `.nys-tabgroup__tabs` and each `<nys-tabpanel>` into\n * `.nys-tabgroup__panels`. If a panel has an `aria-labelledby` attribute,\n * it is explicitly paired with the tab it references; otherwise panels are\n * paired with tabs by index order. After sorting, calls `_applySelection`\n * using the first element that already has a `selected` attribute, or\n * index `0` if none is found.\n *\n * @param e - The `Event` fired by the `<slot>` element on slot change.\n * @returns void\n */\n private _sortChildren(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const assigned = slot.assignedElements();\n\n const tabsContainer = this.shadowRoot?.querySelector(\".nys-tabgroup__tabs\");\n const panelsContainer = this.shadowRoot?.querySelector(\n \".nys-tabgroup__panels\",\n );\n if (!tabsContainer || !panelsContainer) return;\n\n const tabs: HTMLElement[] = [];\n const panelsByRef = new Map<string, HTMLElement>();\n const panelsWithoutRef: HTMLElement[] = [];\n\n assigned.forEach((child) => {\n const tag = child.tagName.toLowerCase();\n if (tag === \"nys-tab\") {\n tabsContainer.appendChild(child);\n tabs.push(child as HTMLElement);\n } else if (tag === \"nys-tabpanel\") {\n panelsContainer.appendChild(child);\n const panel = child as HTMLElement;\n const ariaLabelledBy = panel.getAttribute(\"aria-labelledby\");\n if (ariaLabelledBy) {\n panelsByRef.set(ariaLabelledBy, panel);\n } else {\n panelsWithoutRef.push(panel);\n }\n }\n });\n\n // Pair panels with tabs: explicit refs first, then remaining panels by index\n const panels: HTMLElement[] = [];\n tabs.forEach((tab) => {\n const tabId = tab.id;\n if (tabId && panelsByRef.has(tabId)) {\n panels.push(panelsByRef.get(tabId)!);\n panelsByRef.delete(tabId);\n } else if (panelsWithoutRef.length > 0) {\n panels.push(panelsWithoutRef.shift()!);\n }\n });\n\n // Append any remaining panels with unresolved references\n panelsByRef.forEach((panel) => panels.push(panel));\n\n // Re-append panels in correct order so _getPanels() reads them in tab order\n panels.forEach((panel) => panelsContainer.appendChild(panel));\n\n // Honor the first selected tab; ignore any others\n const declaredSelectedIndex = tabs.findIndex((t) =>\n t.hasAttribute(\"selected\"),\n );\n const selectedIndex =\n declaredSelectedIndex !== -1 ? declaredSelectedIndex : 0;\n\n this._applySelection(tabs, panels, selectedIndex);\n }\n\n /**\n * Handles the `nys-tab-select` custom event bubbled up from a child\n * `<nys-tab>`.\n *\n * Resolves the originating `<nys-tab>` via `composedPath()` (required\n * because the event crosses shadow DOM boundaries), determines its index\n * among the current tab list, and delegates to `_applySelection`.\n *\n * @param e - The `Event` (cast to `CustomEvent`) dispatched by `<nys-tab>`.\n * @returns void\n */\n private _handleTabSelect(e: Event): void {\n const selectedTab = (e as CustomEvent)\n .composedPath()\n .find(\n (el) => (el as HTMLElement).tagName?.toLowerCase() === \"nys-tab\",\n ) as HTMLElement | undefined;\n if (!selectedTab) return;\n\n const tabs = this._getTabs();\n const panels = this._getPanels();\n const selectedIndex = tabs.indexOf(selectedTab);\n if (selectedIndex === -1) return;\n\n this._applySelection(tabs, panels, selectedIndex);\n }\n\n /**\n * Implements the ARIA radio-button keyboard pattern:\n * - `ArrowRight` — moves focus to the next enabled tab (wraps).\n * - `ArrowLeft` — moves focus to the previous enabled tab (wraps).\n *\n * Focus is moved without changing selection; Enter / Space on the newly\n * focused tab (handled by `<nys-tab>._handleKeydown`) confirm selection.\n *\n * The currently focused tab is resolved via `composedPath()` because focus\n * may sit on a shadow-DOM descendant of `<nys-tab>` rather than the host\n * itself.\n *\n * Disabled tabs are excluded from navigation and will never receive focus\n * via arrow keys.\n *\n * @param e - The `KeyboardEvent` from the tablist `keydown` listener.\n * @returns void\n */\n private _handleKeydown(e: KeyboardEvent): void {\n const tabs = this._getTabs().filter((t) => !t.hasAttribute(\"disabled\"));\n if (tabs.length === 0) return;\n\n const focusedTab = (e.composedPath() as HTMLElement[]).find(\n (el) => el.tagName?.toLowerCase() === \"nys-tab\",\n );\n const currentIndex = focusedTab ? tabs.indexOf(focusedTab) : -1;\n\n if (currentIndex === -1) return;\n\n const prevKey = \"ArrowLeft\";\n const nextKey = \"ArrowRight\";\n\n let newIndex = currentIndex;\n\n switch (e.key) {\n case prevKey:\n newIndex = (currentIndex - 1 + tabs.length) % tabs.length;\n break;\n case nextKey:\n newIndex = (currentIndex + 1) % tabs.length;\n break;\n default:\n return;\n }\n\n if (newIndex === currentIndex) return;\n\n // Move focus only — do not change selection\n (tabs[newIndex] as HTMLElement & { focus?: () => void }).focus?.();\n }\n\n /*\n * handles the horizontal scroll of the tab list when the user scrolls on the mouse wheel.\n */\n private _handleWheel = (e: WheelEvent): void => {\n if (e.deltaY === 0) return;\n e.preventDefault();\n this._tabsEl.scrollLeft += e.deltaY;\n };\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n return html`\n <div class=\"nys-tabgroup\" @nys-tab-select=${this._handleTabSelect}>\n <div class=\"nys-tabgroup__tabs-container\">\n <div class=\"nys-tabgroup__tabs-background\"></div>\n <div class=\"scroll-shadow scroll-shadow--left\"></div>\n <div\n class=\"nys-tabgroup__tabs\"\n role=\"tablist\"\n aria-label=${this.name}\n @keydown=${this._handleKeydown}\n ></div>\n <div class=\"scroll-shadow scroll-shadow--right\"></div>\n </div>\n <div class=\"nys-tabgroup__panels\"></div>\n <slot @slotchange=${this._sortChildren}></slot>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-tabgroup\")) {\n customElements.define(\"nys-tabgroup\", NysTabgroup);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tabpanel>` is a content panel paired with a `<nys-tab>` inside a\n * `<nys-tabgroup>`.\n *\n * Pairing is determined by render order: the Nth `<nys-tabpanel>` child of a\n * `<nys-tabgroup>` corresponds to the Nth `<nys-tab>` child.\n * `aria-labelledby` and the `hidden` attribute are managed externally by\n * `<nys-tabgroup>` via `_applySelection`; do not set them directly.\n *\n * @element nys-tabpanel\n *\n * @slot - Default slot for panel content. Rendered inside a wrapper `<div>`\n * with the `.nys-tabpanel` class for styling.\n *\n * @example Panel content is wrapped by `<nys-tabpanel>`.\n * ```html\n * <!-- Panels are paired by position with <nys-tab> elements in the same <nys-tabgroup>. -->\n * <nys-tabgroup name=\"Steps\">\n * <nys-tab label=\"Step 1\"></nys-tab>\n * <nys-tab label=\"Step 2\"></nys-tab>\n * <nys-tabpanel>\n * <h2>Step 1: Enter your information</h2>\n * <p>Fill out the form below.</p>\n * </nys-tabpanel>\n * <nys-tabpanel>\n * <h2>Step 2: Review and submit</h2>\n * <p>Confirm your details before submitting.</p>\n * </nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTabpanel extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the panel element.\n * If not provided, one is auto-generated in `connectedCallback`.\n * Reflected to the DOM attribute so `aria-controls` references on sibling\n * `<nys-tab>` elements resolve correctly.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tabpanel-${Date.now()}-${componentIdCounter++}`;\n }\n this.setAttribute(\"role\", \"tabpanel\");\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n return html`\n <div class=\"nys-tabpanel\" tabindex=\"0\">\n <slot></slot>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-tabpanel\")) {\n customElements.define(\"nys-tabpanel\", NysTabpanel);\n}\n"],"names":["componentIdCounter","_NysTab","LitElement","e","changed","options","html","unsafeCSS","styles","NysTab","__decorateClass","property","_NysTabgroup","scrollLeft","scrollWidth","clientWidth","canScrollLeft","canScrollRight","root","tabs","panels","selectedIndex","tab","i","isSelected","panel","assigned","tabsContainer","panelsContainer","panelsByRef","panelsWithoutRef","child","tag","ariaLabelledBy","tabId","declaredSelectedIndex","t","selectedTab","el","focusedTab","currentIndex","prevKey","nextKey","newIndex","NysTabgroup","_NysTabpanel","NysTabpanel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nys-tab.js","sources":["../src/nys-tab.ts","../src/nys-tabgroup.ts","../src/nys-tabpanel.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tab>` is a single tab within a `<nys-tabgroup>`.\n *\n * The host element carries `role=\"tab\"`, `tabindex`, `aria-selected`,\n * `aria-controls`, and `aria-disabled` so assistive technologies see the\n * correct ARIA tab semantics on the element that is actually focused.\n * `<nys-tabgroup>` manages `tabindex`, `aria-selected`, and `aria-controls`\n * via `_applySelection`; do not set them directly on this element.\n *\n * @element nys-tab\n *\n * @fires nys-tab-select - Dispatched when the tab is activated via click or\n * Enter / Space. Bubbles and crosses shadow DOM boundaries.\n * `detail: { id: string, label: string }`\n * @fires nys-tab-focus - Dispatched when the host receives focus. Bubbles and\n * crosses shadow DOM boundaries. `detail: { id: string }`\n * @fires nys-tab-blur - Dispatched when the host loses focus. Bubbles and\n * crosses shadow DOM boundaries. `detail: { id: string }`\n *\n * @slot - No slots; content is derived from the `label` property.\n *\n * @example `<nys-tab>` and `<nys-tabpanel>` should always be wrapped by `<nys-tabgroup>`\n * ```html\n * <!-- Always place <nys-tab> elements inside a <nys-tabgroup>. -->\n * <nys-tabgroup name=\"My Tabs\">\n * <nys-tab label=\"Overview\"></nys-tab>\n * <nys-tab label=\"Details\" selected></nys-tab>\n * <nys-tab label=\"Archived\" disabled></nys-tab>\n * <nys-tabpanel><p>Overview content</p></nys-tabpanel>\n * <nys-tabpanel><p>Details content (shown by default)</p></nys-tabpanel>\n * <nys-tabpanel><p>Archived content</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTab extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the tab element.\n * Reflected to the DOM attribute so `aria-controls` references resolve.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n /**\n * Visible text label rendered inside the inner `<span>`.\n *\n * @attr label\n */\n @property({ type: String }) label = \"\";\n\n /**\n * Whether this tab is the currently active tab.\n * Managed by `<nys-tabgroup>`; reflected for CSS attribute selectors.\n *\n * @attr selected\n */\n @property({ type: Boolean, reflect: true }) selected = false;\n\n /**\n * Whether this tab is disabled.\n * Reflected to the DOM attribute for CSS styling.\n *\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Sets `role=\"tab\"` and `tabindex=\"-1\"` on the host (the element that AT\n * will read and that receives keyboard focus). Attaches host-level listeners\n * for keydown, focus, blur, and click so that interaction events work\n * correctly on the host element itself.\n *\n * Click is handled at the host level so iOS VoiceOver double-tap (which\n * dispatches `click` directly on the host because of `role=\"tab\"`, bypassing\n * shadow-DOM children) activates the tab. Normal taps land on the inner\n * `<span>` and bubble up to this listener.\n *\n * `<nys-tabgroup>` overrides `tabindex` to `\"0\"` on the selected tab.\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tab-${Date.now()}-${componentIdCounter++}`;\n }\n this.setAttribute(\"role\", \"tab\");\n this.setAttribute(\"tabindex\", \"-1\");\n this.addEventListener(\"keydown\", this._onKeydown);\n this.addEventListener(\"focus\", this._onFocus);\n this.addEventListener(\"blur\", this._onBlur);\n this.addEventListener(\"click\", this._onClick);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"keydown\", this._onKeydown);\n this.removeEventListener(\"focus\", this._onFocus);\n this.removeEventListener(\"blur\", this._onBlur);\n this.removeEventListener(\"click\", this._onClick);\n }\n\n /**\n * Keeps `aria-disabled` on the host in sync with the `disabled` property so\n * AT perceives the disabled state on the element it actually focuses.\n */\n updated(changed: Map<string, unknown>) {\n if (changed.has(\"disabled\")) {\n if (this.disabled) {\n this.setAttribute(\"aria-disabled\", \"true\");\n } else {\n this.removeAttribute(\"aria-disabled\");\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public API\n // ---------------------------------------------------------------------------\n\n /**\n * Focuses the host element. The host carries `role=\"tab\"` and `tabindex`,\n * so it is the correct element for AT to land on.\n */\n public focus(options?: FocusOptions): void {\n super.focus(options);\n }\n\n // ---------------------------------------------------------------------------\n // Event Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Enter / Space on the focused host activate the tab.\n * Arrow-key navigation is handled one level up by `<nys-tabgroup>`.\n */\n private _onKeydown = (e: KeyboardEvent): void => {\n if (this.disabled) return;\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n this._handleClick();\n };\n\n /**\n * Host focus → dispatch `nys-tab-focus` for external observers.\n */\n private _onFocus = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-focus\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id },\n }),\n );\n };\n\n /**\n * Host blur → dispatch `nys-tab-blur` for external observers.\n */\n private _onBlur = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-blur\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id },\n }),\n );\n };\n\n /**\n * Host-level click handler. Activates the tab regardless of whether the\n * click landed on the inner element (normal pointer/keyboard tap, which\n * bubbles up) or directly on the host (iOS VoiceOver double-tap dispatches\n * `click` on the element with `role=\"tab\"`, bypassing shadow-DOM children).\n */\n private _onClick = (): void => {\n this._handleClick();\n };\n\n /**\n * Focuses the host then dispatches `nys-tab-select`. Called from both the\n * click handler and the keydown handler.\n */\n private _handleClick(): void {\n if (this.disabled) return;\n this.focus();\n this.dispatchEvent(\n new CustomEvent(\"nys-tab-select\", {\n bubbles: true,\n composed: true,\n detail: { id: this.id, label: this.label },\n }),\n );\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n // Inner element is a non-interactive `<span>` (not `<button>`) so that\n // axe-core's `nested-interactive` rule does not fire — the host already\n // carries `role=\"tab\"` + `tabindex` and is the interactive control.\n // Disabled gating, click activation, and keyboard activation all happen\n // on the host; the span is purely a styling/labeling target.\n return html`<span class=\"nys-tab\">${this.label}</span>`;\n }\n}\n\nif (!customElements.get(\"nys-tab\")) {\n customElements.define(\"nys-tab\", NysTab);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tabgroup>` is the container for `<nys-tab>` and `<nys-tabpanel>`\n * elements.\n *\n * Accepts tabs and panels as flat light-DOM children in any order (interleaved\n * or grouped). On slot change, children are sorted into dedicated shadow-DOM\n * containers, ARIA relationships are wired, and the first selected (or first)\n * tab is activated.\n *\n * Scroll shadows are rendered on either side of the tab list and toggled via\n * `ResizeObserver` and a `scroll` listener so they accurately reflect whether\n * overflow content exists in each direction.\n *\n * Keyboard navigation follows the\n * {@link https://www.w3.org/WAI/ARIA/apg/patterns/tabs/ ARIA Tabs Pattern}:\n * - Arrow keys move focus without changing selection.\n * - Enter / Space confirm selection on the focused tab.\n *\n * @element nys-tabgroup\n *\n * @slot - Accepts `<nys-tab>` and `<nys-tabpanel>` children. Elements are\n * moved into internal shadow-DOM containers on `slotchange`; the slot\n * itself is not rendered visibly.\n *\n * @example Disable a tab using the `disabled` attribute on `<nys-tab>`.\n * ```html\n * <nys-tabgroup name=\"Account Settings\">\n * <nys-tab label=\"Profile\"></nys-tab>\n * <nys-tab label=\"Security\"></nys-tab>\n * <nys-tab label=\"Notifications\" disabled></nys-tab>\n * <nys-tabpanel><p>Manage your profile information.</p></nys-tabpanel>\n * <nys-tabpanel><p>Update your password and 2FA settings.</p></nys-tabpanel>\n * <nys-tabpanel><p>Notification preferences (coming soon).</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n *\n * @example Pre-select a tab using the `selected` attribute on `<nys-tab>`.\n * ```html\n * <nys-tabgroup name=\"Reports\">\n * <nys-tab label=\"Summary\"></nys-tab>\n * <nys-tab label=\"Details\" selected></nys-tab>\n * <nys-tabpanel><p>Summary view</p></nys-tabpanel>\n * <nys-tabpanel><p>Detailed view (shown by default)</p></nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTabgroup extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the tabgroup element.\n * If not provided, one is auto-generated in `connectedCallback`.\n * Reflected to the DOM attribute.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n /**\n * The name of the tab group.\n * Used for form submission and accessibility purposes.\n *\n * @attr name\n */\n @property({ type: String }) name = \"\";\n\n /**\n * Cached in `firstUpdated` and used by `_updateScrollShadows` to read\n * scroll position and dimensions.\n */\n private _tabsEl!: HTMLElement;\n\n /**\n * Reference to the left scroll-shadow overlay element.\n * Receives the `is-visible` class when the tab list is scrolled away from\n * its leftmost position.\n */\n private _shadowLeft!: HTMLElement;\n\n /**\n * Reference to the right scroll-shadow overlay element.\n * Receives the `is-visible` class when overflow content exists to the right\n * of the current scroll position.\n */\n private _shadowRight!: HTMLElement;\n\n /**\n * `ResizeObserver` instance watching `_tabsEl` for size changes.\n * Re-evaluates scroll shadow visibility whenever the tab list is resized\n * (e.g. viewport resize, dynamic tab additions).\n * Stored so it can be disconnected if needed.\n */\n private _resizeObserver?: ResizeObserver;\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Called when the element is inserted into the document.\n * Auto-generates a unique `id` if one was not provided.\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tabgroup-${Date.now()}-${componentIdCounter++}`;\n }\n }\n\n /**\n * Called after the element's shadow DOM has been rendered for the first time.\n *\n * Caches references to the tab list and scroll-shadow elements, performs an\n * initial scroll-shadow evaluation, and attaches:\n * - A `scroll` event listener on `_tabsEl` to update shadows on scroll.\n * - A `ResizeObserver` on `_tabsEl` to update shadows when the container\n * is resized.\n */\n firstUpdated() {\n const root = this.shadowRoot!;\n this._tabsEl = root.querySelector(\".nys-tabgroup__tabs\")!;\n this._shadowLeft = root.querySelector(\".scroll-shadow--left\")!;\n this._shadowRight = root.querySelector(\".scroll-shadow--right\")!;\n\n this._updateScrollShadows();\n\n this._tabsEl.addEventListener(\"scroll\", this._updateScrollShadows);\n this._tabsEl.addEventListener(\"wheel\", this._handleWheel, {\n passive: false,\n });\n\n this._resizeObserver = new ResizeObserver(() =>\n this._updateScrollShadows(),\n );\n this._resizeObserver.observe(this._tabsEl);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this._tabsEl?.removeEventListener(\"scroll\", this._updateScrollShadows);\n this._tabsEl?.removeEventListener(\"wheel\", this._handleWheel);\n\n this._resizeObserver?.disconnect();\n this._resizeObserver = undefined;\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Reads the current scroll state of `_tabsEl` and toggles the `is-visible`\n * class on the left and right shadow overlays accordingly.\n *\n * - Left shadow is visible when `scrollLeft > 0`.\n * - Right shadow is visible when `scrollLeft + clientWidth < scrollWidth`\n * (i.e. content exists beyond the right edge).\n *\n * Defined as an arrow function so it can be passed directly as an event\n * listener without losing `this` context.\n *\n * @returns void\n */\n private _updateScrollShadows = (): void => {\n const { scrollLeft, scrollWidth, clientWidth } = this._tabsEl;\n\n const canScrollLeft = scrollLeft > 0;\n const canScrollRight = scrollLeft + clientWidth < scrollWidth;\n\n this._shadowLeft.classList.toggle(\"is-visible\", canScrollLeft);\n this._shadowRight.classList.toggle(\"is-visible\", canScrollRight);\n };\n\n /**\n * Returns all `<nys-tab>` elements currently residing in the shadow-DOM\n * tabs container, in DOM order.\n *\n * @returns An array of `HTMLElement` references to every `<nys-tab>` child.\n */\n private _getTabs(): HTMLElement[] {\n return Array.from(\n this.shadowRoot\n ?.querySelector(\".nys-tabgroup__tabs\")\n ?.querySelectorAll(\"nys-tab\") ?? [],\n ) as HTMLElement[];\n }\n\n /**\n * Returns all `<nys-tabpanel>` elements currently residing in the\n * shadow-DOM panels container, in DOM order.\n *\n * @returns An array of `HTMLElement` references to every `<nys-tabpanel>` child.\n */\n private _getPanels(): HTMLElement[] {\n return Array.from(\n this.shadowRoot\n ?.querySelector(\".nys-tabgroup__panels\")\n ?.querySelectorAll(\"nys-tabpanel\") ?? [],\n ) as HTMLElement[];\n }\n\n /**\n * Single source of truth for ARIA wiring, `tabindex`, and panel visibility.\n *\n * For each index `i`:\n * - Sets `selected` / removes `selected` attribute on `tabs[i]`.\n * - Sets `aria-controls` on `tabs[i]` to the `id` of `panels[i]`.\n * - Sets `aria-labelledby` on `panels[i]` to the `id` of `tabs[i]`.\n * - Removes `hidden` from `panels[selectedIndex]`; adds it to all others.\n *\n * Must be called any time the selected tab changes (initial render and\n * subsequent user interactions).\n *\n * @param tabs - Ordered array of `<nys-tab>` elements to update.\n * @param panels - Ordered array of `<nys-tabpanel>` elements to update.\n * Must be the same length as `tabs` for correct pairing.\n * @param selectedIndex - Zero-based index of the tab/panel pair to activate.\n * @returns void\n */\n private _applySelection(\n tabs: HTMLElement[],\n panels: HTMLElement[],\n selectedIndex: number,\n ): void {\n tabs.forEach((tab, i) => {\n const isSelected = i === selectedIndex;\n const panel = panels[i];\n tab.setAttribute(\"aria-selected\", isSelected ? \"true\" : \"false\");\n tab.setAttribute(\"tabindex\", isSelected ? \"0\" : \"-1\");\n if (panel?.id) {\n tab.setAttribute(\"aria-controls\", panel.id);\n }\n if (isSelected) {\n tab.setAttribute(\"selected\", \"\");\n } else {\n tab.removeAttribute(\"selected\");\n }\n });\n\n panels.forEach((panel, i) => {\n const isSelected = i === selectedIndex;\n const tab = tabs[i];\n if (tab) {\n panel.setAttribute(\"aria-labelledby\", tab.id);\n }\n if (isSelected) {\n panel.removeAttribute(\"hidden\");\n } else {\n panel.setAttribute(\"hidden\", \"\");\n }\n });\n }\n\n // ---------------------------------------------------------------------------\n // Event Handlers\n // ---------------------------------------------------------------------------\n\n /**\n * Handles `slotchange` on the default slot.\n *\n * Iterates over all assigned elements and moves each `<nys-tab>` into\n * `.nys-tabgroup__tabs` and each `<nys-tabpanel>` into\n * `.nys-tabgroup__panels`. If a panel has an `aria-labelledby` attribute,\n * it is explicitly paired with the tab it references; otherwise panels are\n * paired with tabs by index order. After sorting, calls `_applySelection`\n * using the first element that already has a `selected` attribute, or\n * index `0` if none is found.\n *\n * @param e - The `Event` fired by the `<slot>` element on slot change.\n * @returns void\n */\n private _sortChildren(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const assigned = slot.assignedElements();\n\n const tabsContainer = this.shadowRoot?.querySelector(\".nys-tabgroup__tabs\");\n const panelsContainer = this.shadowRoot?.querySelector(\n \".nys-tabgroup__panels\",\n );\n if (!tabsContainer || !panelsContainer) return;\n\n const tabs: HTMLElement[] = [];\n const panelsByRef = new Map<string, HTMLElement>();\n const panelsWithoutRef: HTMLElement[] = [];\n\n assigned.forEach((child) => {\n const tag = child.tagName.toLowerCase();\n if (tag === \"nys-tab\") {\n tabsContainer.appendChild(child);\n tabs.push(child as HTMLElement);\n } else if (tag === \"nys-tabpanel\") {\n panelsContainer.appendChild(child);\n const panel = child as HTMLElement;\n const ariaLabelledBy = panel.getAttribute(\"aria-labelledby\");\n if (ariaLabelledBy) {\n panelsByRef.set(ariaLabelledBy, panel);\n } else {\n panelsWithoutRef.push(panel);\n }\n }\n });\n\n // Pair panels with tabs: explicit refs first, then remaining panels by index\n const panels: HTMLElement[] = [];\n tabs.forEach((tab) => {\n const tabId = tab.id;\n if (tabId && panelsByRef.has(tabId)) {\n panels.push(panelsByRef.get(tabId)!);\n panelsByRef.delete(tabId);\n } else if (panelsWithoutRef.length > 0) {\n panels.push(panelsWithoutRef.shift()!);\n }\n });\n\n // Append any remaining panels with unresolved references\n panelsByRef.forEach((panel) => panels.push(panel));\n\n // Re-append panels in correct order so _getPanels() reads them in tab order\n panels.forEach((panel) => panelsContainer.appendChild(panel));\n\n // Honor the first selected tab; ignore any others\n const declaredSelectedIndex = tabs.findIndex((t) =>\n t.hasAttribute(\"selected\"),\n );\n const selectedIndex =\n declaredSelectedIndex !== -1 ? declaredSelectedIndex : 0;\n\n this._applySelection(tabs, panels, selectedIndex);\n }\n\n /**\n * Handles the `nys-tab-select` custom event bubbled up from a child\n * `<nys-tab>`.\n *\n * Resolves the originating `<nys-tab>` via `composedPath()` (required\n * because the event crosses shadow DOM boundaries), determines its index\n * among the current tab list, and delegates to `_applySelection`.\n *\n * @param e - The `Event` (cast to `CustomEvent`) dispatched by `<nys-tab>`.\n * @returns void\n */\n private _handleTabSelect(e: Event): void {\n const selectedTab = (e as CustomEvent)\n .composedPath()\n .find(\n (el) => (el as HTMLElement).tagName?.toLowerCase() === \"nys-tab\",\n ) as HTMLElement | undefined;\n if (!selectedTab) return;\n\n const tabs = this._getTabs();\n const panels = this._getPanels();\n const selectedIndex = tabs.indexOf(selectedTab);\n if (selectedIndex === -1) return;\n\n this._applySelection(tabs, panels, selectedIndex);\n }\n\n /**\n * Implements the ARIA radio-button keyboard pattern:\n * - `ArrowRight` — moves focus to the next enabled tab (wraps).\n * - `ArrowLeft` — moves focus to the previous enabled tab (wraps).\n *\n * Focus is moved without changing selection; Enter / Space on the newly\n * focused tab (handled by `<nys-tab>._handleKeydown`) confirm selection.\n *\n * The currently focused tab is resolved via `composedPath()` because focus\n * may sit on a shadow-DOM descendant of `<nys-tab>` rather than the host\n * itself.\n *\n * Disabled tabs are excluded from navigation and will never receive focus\n * via arrow keys.\n *\n * @param e - The `KeyboardEvent` from the tablist `keydown` listener.\n * @returns void\n */\n private _handleKeydown(e: KeyboardEvent): void {\n const tabs = this._getTabs().filter((t) => !t.hasAttribute(\"disabled\"));\n if (tabs.length === 0) return;\n\n const focusedTab = (e.composedPath() as HTMLElement[]).find(\n (el) => el.tagName?.toLowerCase() === \"nys-tab\",\n );\n const currentIndex = focusedTab ? tabs.indexOf(focusedTab) : -1;\n\n if (currentIndex === -1) return;\n\n const prevKey = \"ArrowLeft\";\n const nextKey = \"ArrowRight\";\n\n let newIndex = currentIndex;\n\n switch (e.key) {\n case prevKey:\n newIndex = (currentIndex - 1 + tabs.length) % tabs.length;\n break;\n case nextKey:\n newIndex = (currentIndex + 1) % tabs.length;\n break;\n default:\n return;\n }\n\n if (newIndex === currentIndex) return;\n\n // Move focus only — do not change selection\n (tabs[newIndex] as HTMLElement & { focus?: () => void }).focus?.();\n }\n\n /*\n * handles the horizontal scroll of the tab list when the user scrolls on the mouse wheel.\n */\n private _handleWheel = (e: WheelEvent): void => {\n if (e.deltaY === 0) return;\n e.preventDefault();\n this._tabsEl.scrollLeft += e.deltaY;\n };\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n return html`\n <div class=\"nys-tabgroup\" @nys-tab-select=${this._handleTabSelect}>\n <div class=\"nys-tabgroup__tabs-container\">\n <div class=\"nys-tabgroup__tabs-background\"></div>\n <div class=\"scroll-shadow scroll-shadow--left\"></div>\n <div\n class=\"nys-tabgroup__tabs\"\n role=\"tablist\"\n aria-label=${this.name}\n @keydown=${this._handleKeydown}\n ></div>\n <div class=\"scroll-shadow scroll-shadow--right\"></div>\n </div>\n <div class=\"nys-tabgroup__panels\"></div>\n <slot @slotchange=${this._sortChildren}></slot>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-tabgroup\")) {\n customElements.define(\"nys-tabgroup\", NysTabgroup);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-tab.scss?inline\";\n\n/** @internal Monotonically increasing counter used to generate unique element IDs. */\nlet componentIdCounter = 0;\n\n/**\n * `<nys-tabpanel>` is a content panel paired with a `<nys-tab>` inside a\n * `<nys-tabgroup>`.\n *\n * Pairing is determined by render order: the Nth `<nys-tabpanel>` child of a\n * `<nys-tabgroup>` corresponds to the Nth `<nys-tab>` child.\n * `aria-labelledby` and the `hidden` attribute are managed externally by\n * `<nys-tabgroup>` via `_applySelection`; do not set them directly.\n *\n * @element nys-tabpanel\n *\n * @slot - Default slot for panel content. Rendered inside a wrapper `<div>`\n * with the `.nys-tabpanel` class for styling.\n *\n * @example Panel content is wrapped by `<nys-tabpanel>`.\n * ```html\n * <!-- Panels are paired by position with <nys-tab> elements in the same <nys-tabgroup>. -->\n * <nys-tabgroup name=\"Steps\">\n * <nys-tab label=\"Step 1\"></nys-tab>\n * <nys-tab label=\"Step 2\"></nys-tab>\n * <nys-tabpanel>\n * <h2>Step 1: Enter your information</h2>\n * <p>Fill out the form below.</p>\n * </nys-tabpanel>\n * <nys-tabpanel>\n * <h2>Step 2: Review and submit</h2>\n * <p>Confirm your details before submitting.</p>\n * </nys-tabpanel>\n * </nys-tabgroup>\n * ```\n */\nexport class NysTabpanel extends LitElement {\n static styles = unsafeCSS(styles);\n\n /**\n * Unique identifier for the panel element.\n * If not provided, one is auto-generated in `connectedCallback`.\n * Reflected to the DOM attribute so `aria-controls` references on sibling\n * `<nys-tab>` elements resolve correctly.\n *\n * @attr id\n */\n @property({ type: String, reflect: true }) id = \"\";\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-tabpanel-${Date.now()}-${componentIdCounter++}`;\n }\n this.setAttribute(\"role\", \"tabpanel\");\n }\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n\n render() {\n return html`\n <div class=\"nys-tabpanel\" tabindex=\"0\">\n <slot></slot>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-tabpanel\")) {\n customElements.define(\"nys-tabpanel\", NysTabpanel);\n}\n"],"names":["componentIdCounter","_NysTab","LitElement","e","changed","options","html","unsafeCSS","styles","NysTab","__decorateClass","property","_NysTabgroup","scrollLeft","scrollWidth","clientWidth","canScrollLeft","canScrollRight","root","tabs","panels","selectedIndex","tab","i","isSelected","panel","assigned","tabsContainer","panelsContainer","panelsByRef","panelsWithoutRef","child","tag","ariaLabelledBy","tabId","declaredSelectedIndex","t","selectedTab","el","focusedTab","currentIndex","prevKey","nextKey","newIndex","NysTabgroup","_NysTabpanel","NysTabpanel"],"mappings":"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"}
|
package/dist/nys-tabgroup.d.ts
CHANGED
|
@@ -101,6 +101,7 @@ export declare class NysTabgroup extends LitElement {
|
|
|
101
101
|
* is resized.
|
|
102
102
|
*/
|
|
103
103
|
firstUpdated(): void;
|
|
104
|
+
disconnectedCallback(): void;
|
|
104
105
|
/**
|
|
105
106
|
* Reads the current scroll state of `_tabsEl` and toggles the `is-visible`
|
|
106
107
|
* class on the left and right shadow overlays accordingly.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nysds/nys-tab",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "The Tab component from the NYS Design System.",
|
|
5
5
|
"module": "dist/nys-tab.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"lit-analyze": "lit-analyzer '*.ts'"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@nysds/nys-button": "1.
|
|
26
|
+
"@nysds/nys-button": "1.19.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"lit": "^3.3.1",
|