{"_id":"@aarongustafson/tabbed-interface","_rev":"6-455227b7781b69dccbb2b900a5ede4e5","name":"@aarongustafson/tabbed-interface","dist-tags":{"latest":"2.1.1"},"versions":{"1.0.0":{"name":"@aarongustafson/tabbed-interface","version":"1.0.0","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"url":"https://www.aaron-gustafson.com/","name":"Aaron Gustafson","email":"aaron@easy-designs.net"},"license":"MIT","_id":"@aarongustafson/tabbed-interface@1.0.0","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"homepage":"https://github.com/aarongustafson/tabbed-interface#readme","bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"dist":{"shasum":"9eb87440a0bd0eaab1c673903f10601655affef9","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-1.0.0.tgz","fileCount":7,"integrity":"sha512-YsBGwPXnC+o3Vmxhsm+nBp91Pt7MuCtqQNLVot4IUEJAF/5sfKkeUAllcBW60LnnxYlF2u4o6pheaJVgj3zUvA==","signatures":[{"sig":"MEUCIQDbCWB8sfYWEAva/peSYvTfJ+ogOiiP6EQfgoOS7xPyrAIgMiQu1nnbTNyicdTrmbLRL3fN8wamIrSTu38mK6d22Ew=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30617},"main":"index.js","type":"module","module":"tabbed-interface.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":"./index.js"},"./define.js":{"import":"./define.js"},"./tabbed-interface.js":{"import":"./tabbed-interface.js"},"./custom-elements.json":"./custom-elements.json"},"gitHead":"69143d8c85a3c99ca0cba8936a6babe938447328","scripts":{"lint":"npm run lint:eslint && npm run lint:prettier","test":"vitest","format":"npm run format:eslint && npm run format:prettier","test:ui":"vitest --ui","test:run":"vitest run","lint:eslint":"eslint .","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","test:coverage":"vitest run --coverage","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore"},"_npmUser":{"name":"aarongustafson","email":"aaron@easy-designs.net"},"repository":{"url":"git+https://github.com/aarongustafson/tabbed-interface.git","type":"git"},"_npmVersion":"10.8.2","description":"A web component that transforms heading-structured content into an accessible tabbed interface","directories":{},"_nodeVersion":"20.18.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"customElements":"custom-elements.json","devDependencies":{"eslint":"^9.39.1","vitest":"^4.0.10","prettier":"^3.6.2","happy-dom":"^20.0.10","@vitest/ui":"^4.0.10","@vitest/coverage-v8":"^4.0.10","@testing-library/dom":"^10.4.1","@open-wc/eslint-config":"^13.0.0","eslint-config-prettier":"^10.1.8","@testing-library/user-event":"^14.6.1"},"_npmOperationalInternal":{"tmp":"tmp/tabbed-interface_1.0.0_1764481206638_0.2759805358959464","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@aarongustafson/tabbed-interface","version":"1.0.4","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"url":"https://www.aaron-gustafson.com/","name":"Aaron Gustafson","email":"aaron@easy-designs.net"},"license":"MIT","_id":"@aarongustafson/tabbed-interface@1.0.4","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"homepage":"https://github.com/aarongustafson/tabbed-interface#readme","bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"dist":{"shasum":"2d6da02eed0694c715ce263997c98663aef93916","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-1.0.4.tgz","fileCount":7,"integrity":"sha512-bK0qC/RcKdgjRCz8aViy4aRvYkr/qDhgZQVU279wNYVLh8EgZQYy4mfDDrsW/pEKZBNVTlaS51LPXPpLIs6nIA==","signatures":[{"sig":"MEUCIHtnWXaq4mBN5TZx0/zI5+F0DwAMQPzdfuC3AWboC1jIAiEA6Pfsmi5cFxFgPRieD/d79k7eLChdfKZDujjHT9E5EQw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aarongustafson%2ftabbed-interface@1.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":31071},"main":"index.js","type":"module","module":"tabbed-interface.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":"./index.js"},"./define.js":{"import":"./define.js"},"./tabbed-interface.js":{"import":"./tabbed-interface.js"},"./custom-elements.json":"./custom-elements.json"},"gitHead":"45b6e2004bb4676c058ef6f3bbad75421b583416","scripts":{"lint":"npm run lint:eslint && npm run lint:prettier","test":"vitest","format":"npm run format:eslint && npm run format:prettier","test:ui":"vitest --ui","test:run":"vitest run","lint:eslint":"eslint .","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","test:coverage":"vitest run --coverage","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ca4a8871-cafd-4cbf-8306-1f6f5b27f5fa"}},"repository":{"url":"git+https://github.com/aarongustafson/tabbed-interface.git","type":"git"},"_npmVersion":"11.6.4","description":"A web component that transforms heading-structured content into an accessible tabbed interface","directories":{},"_nodeVersion":"20.19.5","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"customElements":"custom-elements.json","devDependencies":{"eslint":"^9.39.1","vitest":"^4.0.10","prettier":"^3.6.2","happy-dom":"^20.0.10","@vitest/ui":"^4.0.10","@vitest/coverage-v8":"^4.0.10","@testing-library/dom":"^10.4.1","@open-wc/eslint-config":"^13.0.0","eslint-config-prettier":"^10.1.8","@testing-library/user-event":"^14.6.1"},"_npmOperationalInternal":{"tmp":"tmp/tabbed-interface_1.0.4_1764563463316_0.8087938647043462","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@aarongustafson/tabbed-interface","version":"2.0.0","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"url":"https://www.aaron-gustafson.com/","name":"Aaron Gustafson","email":"aaron@easy-designs.net"},"license":"MIT","_id":"@aarongustafson/tabbed-interface@2.0.0","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"homepage":"https://github.com/aarongustafson/tabbed-interface#readme","bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"dist":{"shasum":"3a106e87537e6e0d63291db208b35ee86e65d284","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-2.0.0.tgz","fileCount":7,"integrity":"sha512-8cYNqmSp8gj9RLPaSO+XhlY+38qcRCnXQE+fIZh4sGkuQl68CqBRrfEaoM8mv2vKn5eYoABFs/Rs4RJHPaJUOQ==","signatures":[{"sig":"MEUCIB0Plhh4OHvhhtI7aAw60mzYwzKneMF5YDkg5B6OHiEnAiEAgNLa4KZF+DaQbkCdTVWIX5qNvGQe/zKTYLvQ4Pa0KOw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aarongustafson%2ftabbed-interface@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":31425},"main":"index.js","type":"module","module":"tabbed-interface.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":"./index.js"},"./define.js":{"import":"./define.js"},"./tabbed-interface.js":{"import":"./tabbed-interface.js"},"./custom-elements.json":"./custom-elements.json"},"gitHead":"edf3684ea7da078ed742a5431430c0fa8f0ebf2e","scripts":{"lint":"npm run lint:eslint && npm run lint:prettier","test":"vitest","format":"npm run format:eslint && npm run format:prettier","test:ui":"vitest --ui","test:run":"vitest run","lint:eslint":"eslint .","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","test:coverage":"vitest run --coverage","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ca4a8871-cafd-4cbf-8306-1f6f5b27f5fa"}},"repository":{"url":"git+https://github.com/aarongustafson/tabbed-interface.git","type":"git"},"_npmVersion":"11.6.4","description":"A web component that transforms heading-structured content into an accessible tabbed interface","directories":{},"_nodeVersion":"20.19.6","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"customElements":"custom-elements.json","devDependencies":{"eslint":"^9.39.1","vitest":"^4.0.10","prettier":"^3.6.2","happy-dom":"^20.0.10","@vitest/ui":"^4.0.10","@vitest/coverage-v8":"^4.0.10","@testing-library/dom":"^10.4.1","@open-wc/eslint-config":"^13.0.0","eslint-config-prettier":"^10.1.8","@testing-library/user-event":"^14.6.1"},"_npmOperationalInternal":{"tmp":"tmp/tabbed-interface_2.0.0_1765213822828_0.29243756660487197","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@aarongustafson/tabbed-interface","version":"2.0.1","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"url":"https://www.aaron-gustafson.com/","name":"Aaron Gustafson","email":"aaron@easy-designs.net"},"license":"MIT","_id":"@aarongustafson/tabbed-interface@2.0.1","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"homepage":"https://github.com/aarongustafson/tabbed-interface#readme","bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"dist":{"shasum":"f78b35465644e0670923a637455de30ffc378e26","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-2.0.1.tgz","fileCount":7,"integrity":"sha512-nwI+sgXx8OPnIEiiwhb0SImY/AhdZ0bmc9H+wLyhqOAglnM4mq3VMLx/qy3ypB4ICEd/zV9Eyrt/d5y31Ztpcg==","signatures":[{"sig":"MEYCIQClv1GXQWF6w4MgiUqgdHn0QtJalWsfRXNhSQvNOBw5nAIhALA6e7LYvOtRSEI433icR0CU9NxfWvturfXyRjjdmnwm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aarongustafson%2ftabbed-interface@2.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":31726},"main":"index.js","type":"module","module":"tabbed-interface.js","engines":{"node":">=14.0.0"},"exports":{".":{"import":"./index.js"},"./define.js":{"import":"./define.js"},"./tabbed-interface.js":{"import":"./tabbed-interface.js"},"./custom-elements.json":"./custom-elements.json"},"gitHead":"e3393b177d8fbee9856fbdbc98b26e33a6fe301d","scripts":{"lint":"npm run lint:eslint && npm run lint:prettier","test":"vitest","format":"npm run format:eslint && npm run format:prettier","test:ui":"vitest --ui","version":"node scripts/update-demo-versions.js && git add demo/esm.html","test:run":"vitest run","lint:eslint":"eslint .","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","test:coverage":"vitest run --coverage","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ca4a8871-cafd-4cbf-8306-1f6f5b27f5fa"}},"repository":{"url":"git+https://github.com/aarongustafson/tabbed-interface.git","type":"git"},"_npmVersion":"11.7.0","description":"A web component that transforms heading-structured content into an accessible tabbed interface","directories":{},"_nodeVersion":"20.19.6","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"customElements":"custom-elements.json","devDependencies":{"eslint":"^9.39.1","vitest":"^4.0.10","prettier":"^3.6.2","happy-dom":"^20.0.10","@vitest/ui":"^4.0.10","@vitest/coverage-v8":"^4.0.10","@testing-library/dom":"^10.4.1","@open-wc/eslint-config":"^13.0.0","eslint-config-prettier":"^10.1.8","@testing-library/user-event":"^14.6.1"},"_npmOperationalInternal":{"tmp":"tmp/tabbed-interface_2.0.1_1765309885017_0.926525806529723","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@aarongustafson/tabbed-interface","version":"2.1.0","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"url":"https://www.aaron-gustafson.com/","name":"Aaron Gustafson","email":"aaron@easy-designs.net"},"license":"MIT","_id":"@aarongustafson/tabbed-interface@2.1.0","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"homepage":"https://github.com/aarongustafson/tabbed-interface#readme","bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"dist":{"shasum":"62bffb4977a44d661554b283384c3a6a61d241c6","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-2.1.0.tgz","fileCount":8,"integrity":"sha512-/oTpFrD0j2rMi2vmHZovijljUB842BMr0Xhl9nejNXQda+4eNN9D5jF7vTv9MccgmSQvJ68DOmXElJbb6HwQ4w==","signatures":[{"sig":"MEUCIHEmvT/5Syfv6QeXrGlBfC3i4xB3N6xfoo0KfXsEEa2nAiEAteUgItPWAIiTXMdvJoIEKHKbSMaZkrr6OSL/u35Nq2M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aarongustafson%2ftabbed-interface@2.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":35934},"main":"index.js","type":"module","module":"tabbed-interface.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":"./index.js"},"./define.js":{"import":"./define.js"},"./tabbed-interface.js":{"types":"./tabbed-interface.d.ts","import":"./tabbed-interface.js"},"./custom-elements.json":"./custom-elements.json"},"gitHead":"56783c19022ca27a05a6a55835dac61611412b22","scripts":{"lint":"npm run lint:eslint && npm run lint:prettier","test":"vitest","format":"npm run format:eslint && npm run format:prettier","test:ui":"vitest --ui","version":"node scripts/update-demo-versions.js && git add demo/esm.html","test:run":"vitest run","lint:eslint":"eslint .","postversion":"git push --follow-tags","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","test:coverage":"vitest run --coverage","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ca4a8871-cafd-4cbf-8306-1f6f5b27f5fa"}},"repository":{"url":"git+https://github.com/aarongustafson/tabbed-interface.git","type":"git"},"_npmVersion":"11.7.0","description":"A web component that transforms heading-structured content into an accessible tabbed interface","directories":{},"_nodeVersion":"20.19.6","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"customElements":"custom-elements.json","devDependencies":{"eslint":"^9.39.1","vitest":"^4.0.10","prettier":"^3.6.2","happy-dom":"^20.0.10","@vitest/ui":"^4.0.10","@vitest/coverage-v8":"^4.0.10","@testing-library/dom":"^10.4.1","@open-wc/eslint-config":"^13.0.0","eslint-config-prettier":"^10.1.8","@testing-library/user-event":"^14.6.1"},"_npmOperationalInternal":{"tmp":"tmp/tabbed-interface_2.1.0_1765726533075_0.1821973379654631","host":"s3://npm-registry-packages-npm-production"}},"2.1.1":{"name":"@aarongustafson/tabbed-interface","version":"2.1.1","description":"A web component that transforms heading-structured content into an accessible tabbed interface","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"author":{"name":"Aaron Gustafson","email":"aaron@easy-designs.net","url":"https://www.aaron-gustafson.com/"},"license":"MIT","homepage":"https://github.com/aarongustafson/tabbed-interface#readme","repository":{"type":"git","url":"git+https://github.com/aarongustafson/tabbed-interface.git"},"bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"type":"module","main":"index.js","module":"tabbed-interface.js","customElements":"custom-elements.json","types":"tabbed-interface.d.ts","exports":{".":{"import":"./index.js"},"./tabbed-interface.js":{"import":"./tabbed-interface.js","types":"./tabbed-interface.d.ts"},"./define.js":{"import":"./define.js"},"./custom-elements.json":"./custom-elements.json"},"engines":{"node":">=20.0.0"},"scripts":{"test":"vitest","test:ui":"vitest --ui","test:run":"vitest run","test:coverage":"vitest run --coverage","lint":"npm run lint:eslint && npm run lint:prettier","format":"npm run format:eslint && npm run format:prettier","lint:eslint":"eslint .","format:eslint":"eslint . --fix","lint:prettier":"prettier \"**/*.js\" --check --ignore-path .gitignore","format:prettier":"prettier \"**/*.js\" --write --ignore-path .gitignore","version":"node scripts/update-demo-versions.js && git add demo/esm.html","postversion":"git push --follow-tags"},"devDependencies":{"@open-wc/eslint-config":"^13.0.0","@testing-library/dom":"^10.4.1","@testing-library/user-event":"^14.6.1","@vitest/coverage-v8":"^4.0.10","@vitest/ui":"^4.0.10","eslint":"^9.39.1","eslint-config-prettier":"^10.1.8","happy-dom":"^20.0.10","prettier":"^3.6.2","vitest":"^4.0.10"},"publishConfig":{"access":"public"},"gitHead":"07806e52d8e1bddb484d41259cac473ee20077cc","_id":"@aarongustafson/tabbed-interface@2.1.1","_nodeVersion":"20.19.6","_npmVersion":"11.7.0","dist":{"integrity":"sha512-eqceAgpbtjB8u3AH98zrMhNP+ZcoQoieDXVfIbH7D89ifdp1vYtIupkOEskEpPuPrT+mBadYXQyrfsUITFnQGQ==","shasum":"f6208d6de730f305d5375ae1358376ecb93f8e42","tarball":"https://registry.npmjs.org/@aarongustafson/tabbed-interface/-/tabbed-interface-2.1.1.tgz","fileCount":8,"unpackedSize":35969,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aarongustafson%2ftabbed-interface@2.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDs/WPw3YWoG0FfUkDRFdd/njo1nG/BpR0xZzK1+bUiVgIhANw5mnAltJahbuYPalfElNljT66aJBcgfTM85SS4y8pQ"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ca4a8871-cafd-4cbf-8306-1f6f5b27f5fa"}},"directories":{},"maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/tabbed-interface_2.1.1_1765774094356_0.20324410537757398"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-30T05:40:06.553Z","modified":"2025-12-15T04:48:14.878Z","1.0.0":"2025-11-30T05:40:06.861Z","1.0.4":"2025-12-01T04:31:03.489Z","2.0.0":"2025-12-08T17:10:22.980Z","2.0.1":"2025-12-09T19:51:25.151Z","2.1.0":"2025-12-14T15:35:33.264Z","2.1.1":"2025-12-15T04:48:14.531Z"},"bugs":{"url":"https://github.com/aarongustafson/tabbed-interface/issues"},"author":{"name":"Aaron Gustafson","email":"aaron@easy-designs.net","url":"https://www.aaron-gustafson.com/"},"license":"MIT","homepage":"https://github.com/aarongustafson/tabbed-interface#readme","keywords":["html","custom element","web component","tabs","tabbed interface","accessibility","aria"],"repository":{"type":"git","url":"git+https://github.com/aarongustafson/tabbed-interface.git"},"description":"A web component that transforms heading-structured content into an accessible tabbed interface","maintainers":[{"name":"aarongustafson","email":"aaron@easy-designs.net"}],"readme":"# Tabbed Interface Web Component\n\n[![npm version](https://img.shields.io/npm/v/@aarongustafson/tabbed-interface.svg)](https://www.npmjs.com/package/@aarongustafson/tabbed-interface)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/aarongustafson/tabbed-interface/ci.yml?branch=main)](https://github.com/aarongustafson/tabbed-interface/actions)\n\nA web component that transforms heading-structured content into an accessible tabbed interface. This is a modern web component port of Aaron Gustafson's original [TabInterface](https://github.com/easy-designs/TabInterface.js).\n\n## Demo\n\n- [Live Demo](https://aarongustafson.github.io/tabbed-interface/demo/) ([Source](./demo/index.html))\n- [unpkg Demo](https://aarongustafson.github.io/tabbed-interface/demo/unpkg.html) ([Source](./demo/unpkg.html))\n- [esm.sh Demo](https://aarongustafson.github.io/tabbed-interface/demo/esm.html) ([Source](./demo/esm.html))\n\n## Features\n\n- **Progressive Enhancement**: Works with semantic HTML structure\n- **Accessibility**: Full ARIA support and keyboard navigation\n- **Customizable**: Extensive CSS custom properties for styling\n- **Lightweight**: No dependencies, pure vanilla JavaScript\n- **Modern**: Uses Shadow DOM and ES Modules\n- **TypeScript-ready**: Ships bundled type definitions for editors and build tooling\n\n## TypeScript & Framework Support\n\n- Bundled `.d.ts` files describe both `TabbedInterfaceElement` and `defineTabbedInterface`, so editors, bundlers, and framework toolchains get type information automatically.\n- The `showHeaders`, `tablistAfter`, `autoActivate`, and `defaultTab` properties reflect to attributes, keeping declarative markup and imperative code in sync.\n- A private `upgradeProperty` helper replays any property assignments that happen before the browser upgrades the element, which is especially helpful for SSR and hydration workflows.\n- The `defaultTab` property accepts either zero-based indices or heading IDs, making it easy to drive tab selection from reactive state or router parameters.\n\n## Installation\n\n```bash\nnpm install @aarongustafson/tabbed-interface\n```\n\n## Usage\n\n### Basic Usage\n\n```html\n<tabbed-interface>\n  <h2>First Tab</h2>\n  <p>Content for the first tab panel.</p>\n\n  <h2>Second Tab</h2>\n  <p>Content for the second tab panel.</p>\n\n  <h2>Third Tab</h2>\n  <p>Content for the third tab panel.</p>\n</tabbed-interface>\n\n<script type=\"module\">\n  import '@aarongustafson/tabbed-interface/define.js';\n</script>\n```\n\n### Import Options\n\n**Auto-define (browser environments only):**\n```javascript\nimport '@aarongustafson/tabbed-interface/define.js';\n// Registers <tabbed-interface> when customElements is available\n```\n\nPrefer to control when registration happens? Call the helper directly:\n\n```javascript\nimport { defineTabbedInterface } from '@aarongustafson/tabbed-interface/define.js';\n\ndefineTabbedInterface();\n```\n\n**Manual registration:**\n```javascript\nimport { TabbedInterfaceElement } from '@aarongustafson/tabbed-interface';\ncustomElements.define('my-tabs', TabbedInterfaceElement);\n```\n\n## Attributes\n\n| Attribute | Type | Default | Description |\n|-----------|------|---------|-------------|\n| `show-headers` | boolean | `false` | When present, shows headings in tab panels |\n| `tablist-after` | boolean | `false` | When present, positions tab list after content |\n| `default-tab` | string | `\"0\"` | Initial active tab (index or heading ID) |\n| `auto-activate` | boolean | `false` | When present, tabs activate on focus; when absent, use Enter/Space to activate |\n\n### Examples\n\n```html\n<!-- Show headings in panels -->\n<tabbed-interface show-headers>\n  ...\n</tabbed-interface>\n\n<!-- Tabs after content -->\n<tabbed-interface tablist-after>\n  ...\n</tabbed-interface>\n\n<!-- Start on specific tab -->\n<tabbed-interface default-tab=\"2\">\n  ...\n</tabbed-interface>\n\n<!-- Start on tab by heading ID -->\n<tabbed-interface default-tab=\"features\">\n  <h2 id=\"intro\">Introduction</h2>\n  <p>...</p>\n  <h2 id=\"features\">Features</h2>\n  <p>...</p>\n</tabbed-interface>\n\n<!-- Auto-activation (tabs activate on focus) -->\n<tabbed-interface auto-activate>\n  ...\n</tabbed-interface>\n```\n\n## Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `activeIndex` | number | Get/set the currently active tab index |\n| `showHeaders` | boolean | Get/set header visibility |\n| `tablistAfter` | boolean | Get/set tablist position |\n| `autoActivate` | boolean | Get/set auto-activation behavior |\n\n## Methods\n\n| Method | Description |\n|--------|-------------|\n| `next()` | Navigate to the next tab |\n| `previous()` | Navigate to the previous tab |\n| `first()` | Navigate to the first tab |\n| `last()` | Navigate to the last tab |\n\n### Programmatic Control\n\n```javascript\nconst $tabs = document.querySelector('tabbed-interface');\n\n// Navigate\n$tabs.next();\n$tabs.previous();\n$tabs.first();\n$tabs.last();\n\n// Set active tab directly\n$tabs.activeIndex = 2;\n```\n\n## Events\n\n| Event | Detail | Description |\n|-------|--------|-------------|\n| `tabbed-interface:change` | `{ tabId, tabpanelId, tabIndex }` | Fired when active tab changes |\n\n```javascript\ndocument.querySelector('tabbed-interface')\n  .addEventListener('tabbed-interface:change', (e) => {\n    console.log(`Switched to tab ${e.detail.tabIndex}`);\n  });\n```\n\n## Keyboard Navigation\n\n| Key | Action |\n|-----|--------|\n| `Arrow Left/Up` | Previous tab |\n| `Arrow Right/Down` | Next tab |\n| `Home` | First tab |\n| `End` | Last tab |\n| `Enter/Space` | Activate tab (when auto-activate is absent) and focus first focusable element in panel |\n\n## Styling with CSS Parts\n\nStyle the component's shadow DOM elements using CSS `::part()` selectors:\n\n### Available Parts\n\n| Part | Description |\n|------|-------------|\n| `tablist` | The container for all tabs |\n| `tab` | Individual tab buttons |\n| `tabpanel` | Individual tab panel containers |\n\n### Styling Examples\n\n**Basic styling:**\n```css\ntabbed-interface::part(tablist) {\n  gap: 4px;\n  background: #f0f0f0;\n  padding: 8px;\n}\n\ntabbed-interface::part(tab) {\n  padding: 0.75em 1.5em;\n  background: white;\n  border: 1px solid #ccc;\n  border-radius: 4px 4px 0 0;\n  font-weight: 500;\n}\n\ntabbed-interface::part(tab):hover {\n  background: #e9e9e9;\n}\n\ntabbed-interface::part(tabpanel) {\n  padding: 2em;\n  border: 1px solid #ccc;\n  background: white;\n}\n```\n\n**Targeting specific states:**\n```css\n/* Active tab - use attribute selector on the host */\ntabbed-interface::part(tab selected) {\n  background: white;\n  border-bottom-color: white;\n  font-weight: bold;\n}\n\n/* Focus styles */\ntabbed-interface::part(tab):focus-visible {\n  outline: 3px solid blue;\n  outline-offset: 2px;\n}\n```\n\n**Themed variations:**\n```css\n/* Pills style */\n.pills::part(tablist) {\n  gap: 8px;\n  background: transparent;\n}\n\n.pills::part(tab) {\n  border-radius: 20px;\n  background: #e0e0e0;\n}\n\n.pills::part(tab)[aria-selected=\"true\"] {\n  background: #007bff;\n  color: white;\n}\n\n/* Minimal style */\n.minimal::part(tab) {\n  border: none;\n  border-bottom: 2px solid transparent;\n  border-radius: 0;\n  background: transparent;\n}\n\n.minimal::part(tab)[aria-selected=\"true\"] {\n  border-bottom-color: #007bff;\n}\n\n.minimal::part(tabpanel) {\n  border: none;\n  padding-top: 1.5em;\n}\n```\n\n## Custom Tab Titles\n\nUse `data-tab-short-name` to show a different label in the tab than the heading. The full heading text is set as the `aria-label` for screen readers:\n\n```html\n<tabbed-interface>\n  <h2 data-tab-short-name=\"Intro\">Introduction and Getting Started Guide</h2>\n  <p>Full content with the complete heading visible in the panel.</p>\n</tabbed-interface>\n```\n\n## Hash Navigation\n\nThe component supports URL hash navigation. Link to specific tabs:\n\n```html\n<a href=\"#features\">Go to Features</a>\n\n<tabbed-interface>\n  <h2 id=\"intro\">Introduction</h2>\n  <p>...</p>\n  <h2 id=\"features\">Features</h2>\n  <p>...</p>\n</tabbed-interface>\n```\n\n## Browser Support\n\nWorks in all modern browsers supporting:\n- Custom Elements v1\n- Shadow DOM v1\n- ES Modules\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Run tests\nnpm test\n\n# Run tests once\nnpm run test:run\n\n# Lint\nnpm run lint\n\n# Format code\nnpm run format\n```\n\n## License\n\nMIT - See [LICENSE](LICENSE)\n\n## Credits\n\nBased on the [jQuery TabInterface plugin](https://github.com/easy-designs/jquery.TabInterface.js) by Aaron Gustafson, which is itself a port of his original [TabInterface](https://github.com/easy-designs/TabInterface.js).\n","readmeFilename":"README.md"}