npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@francofantomius/material-components

v1.4.1

Published

Reusable, accessible, and lightweight Material Design 3 Web Components built with Lit.

Readme

@francofantomius/material-components

A modern, accessible, and lightweight Material Design 3 (M3) Web Components library built with Lit, Vite, and TypeScript.

Runs natively in all modern browsers and integrates seamlessly with React (18 & 19), Vue 3, Angular, Svelte, Solid, or vanilla HTML/JavaScript without requiring framework-specific wrappers.


Table of Contents


Features

  • Material Design 3: Fully tokenized CSS design tokens for dynamic theming, tonal color palettes, surface containers, elevations 0–5, and light/dark modes.
  • 40+ Core Components & Utilities: Complete suite including Navigation Bars, Rails & Drawers, Date & Time Pickers, Carousels, Menus, Toolbars, Tooltips, Sliders, Bottom/Side Sheets, Data Tables, Media Players, Code Blocks/Linters, Search Bars, Form Elements, Dialogs, Cards, and more.
  • Form-Associated Custom Elements (FACE): Native <form> integration, FormData compatibility, and standard constraint validation (required, checkValidity(), reportValidity()).
  • Automatic ARIA Label Tooltips: Built-in accessible Material Design floating tooltips dynamically displayed for any component with aria-label or title without extra boilerplate.
  • Lightweight & Tree-Shakeable: Pure ESM modules with granular subpath exports (e.g. @francofantomius/material-components/button).
  • TypeScript & Custom Elements Manifest: First-class TypeScript declarations (.d.ts), inline sourcemaps, and standard custom-elements.json for IDE autocomplete.
  • Accessible (a11y): WCAG 2.1 AA compliant contrast ratios, high-visibility focus rings (<md-focus-ring>), keyboard navigation, and ARIA state handling.
  • Framework Agnostic: Works out of the box with React, Vue, Angular, Svelte, Solid, or vanilla HTML/JS.

Installation

# npm
npm install @francofantomius/material-components lit

# pnpm
pnpm add @francofantomius/material-components lit

# yarn
yarn add @francofantomius/material-components lit

# bun
bun add @francofantomius/material-components lit

CDN Quick Start

For quick prototyping or usage directly in HTML without a bundler, import from an ESM CDN:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Material Components Demo</title>
    <!-- Fonts & Icons -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" />

    <!-- Import from CDN (esm.sh / jsdelivr / unpkg) -->
    <script type="module" src="https://esm.sh/@francofantomius/[email protected]"></script>
  </head>
  <body>
    <md-button variant="filled" icon="send">Get Started</md-button>
  </body>
</html>

Quick Start

1. Load Fonts and Icons (Recommended)

Add Google Roboto and Material Symbols Outlined to your HTML <head>:

<!-- Material Symbols Outlined font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />

<!-- Roboto font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" />

2. Import Components

Granular Subpath Imports (Recommended for production)

Import only the components you use to optimize bundle sizes:

import '@francofantomius/material-components/button';
import '@francofantomius/material-components/text-field';
import '@francofantomius/material-components/top-app-bar';
import '@francofantomius/material-components/navigation-drawer';
import '@francofantomius/material-components/table';
import '@francofantomius/material-components/search-bar';
import '@francofantomius/material-components/app-drawer';
import '@francofantomius/material-components/account-menu';
import '@francofantomius/material-components/code';
import '@francofantomius/material-components/player';

Global Bundle Import (Ideal for prototyping)

Registers all components at once:

import '@francofantomius/material-components';

Component Index

| Category | Component Tag(s) | Subpath Export | Key Properties & Attributes | | :--- | :--- | :--- | :--- | | Actions | <md-button> | /button | variant (filled, elevated, tonal, outlined, text), icon, trailing-icon, loading, disabled, href, target, type | | Actions | <md-button-group> | /button-group | orientation (horizontal, vertical), connected | | Actions | <md-split-button> | /split-button | variant (filled, elevated, tonal, outlined), icon, trailing-icon, disabled, open | | Actions | <md-segmented-button>, <md-segmented-button-set> | /segmented-button | selected, disabled, value, label, icon, no-checkmark, multiselect | | Actions | <md-icon-button> | /icon-button | variant (standard, filled, tonal, outlined), icon, selected-icon, toggle, selected, disabled | | Actions | <md-fab> | /fab | size (small, medium, large), label, icon, lowered, disabled | | Actions | <md-fab-menu>, <md-fab-menu-item> | /fab-menu | open, icon, active-icon, direction (up, down, left, right), lowered, label | | Actions | <md-icon> | /icon | name, filled, size | | Actions | <md-toolbar> | /toolbar | variant (floating, docked), center-aligned | | Inputs & Controls | <md-text-field> | /text-field | variant (filled, outlined), label, value, type, placeholder, prefix-text, suffix-text, error, error-text, supporting-text, leading-icon, trailing-icon, maxlength, required | | Inputs & Controls | <md-checkbox> | /checkbox | checked, indeterminate, error, disabled, required, name, value | | Inputs & Controls | <md-switch> | /switch | selected, icons, disabled, name, value | | Inputs & Controls | <md-radio>, <md-radio-group> | /radio | checked, value, name, row, disabled | | Inputs & Controls | <md-slider> | /slider | value, range-start, range-end, min, max, step, discrete, with-ticks, with-label, disabled | | Inputs & Controls | <md-chip>, <md-chip-set> | /chip | variant (assist, filter, input, suggestion), label, icon, selected, removable, disabled | | Inputs & Controls | <md-search-bar>, <md-search> | /search-bar | value, placeholder, active, suggestions, leading-icon, trailing-icon, responsive, collapse-on-mobile, fullscreen | | Date & Time | <md-date-picker> | /date-picker | value, min, max, view (calendar, input), open, headline, modal | | Date & Time | <md-time-picker> | /time-picker | value, format (12h, 24h), view (dial, input), open, headline, modal | | Surfaces & Layout | <md-card> | /card | variant (elevated, filled, outlined), interactive, disabled, href, target | | Surfaces & Layout | <md-dialog> | /dialog | open, headline, icon, cancelable, showModal(), close() | | Surfaces & Layout | <md-side-sheet> | /side-sheet | open, type (modal, standard), pivot (left, right), headline | | Surfaces & Layout | <md-bottom-sheet> | /bottom-sheet | open, scrim, has-handle, headline | | Surfaces & Layout | <md-divider> | /divider | vertical, inset, inset-start, inset-end | | Surfaces & Layout | <md-list>, <md-list-item> | /list | headline, supporting-text, trailing-supporting-text, interactive, disabled, href | | Surfaces & Layout | <md-table>, <md-data-table> | /table | columns, rows, selectable, sortable, paginated, page, page-size, bordered, striped, sticky-header, loading | | Surfaces & Layout | <md-carousel>, <md-carousel-item> | /carousel | layout (multi-browse, hero, uncontained), loop, autoplay, interval | | Communication | <md-badge> | /badge | value, dot, max | | Communication | <md-progress> | /progress | type (linear, circular), value (0 to 1, or indeterminate), buffer, wavy | | Communication | <md-loading-indicator> | /loading-indicator | active, size (small, medium, large), shape | | Communication | <md-snackbar> | /snackbar | open, message, action-text, closeable, timeout-ms, stacked | | Communication | <md-tooltip> | /tooltip | content, rich, headline, position (top, bottom, left, right), delay-ms, interactive | | Navigation | <md-top-app-bar>, <md-top-bar> | /top-app-bar | variant (center-aligned, small, medium, large), headline, subtitle, elevated, fixed | | Navigation | <md-navigation-bar>, <md-navigation-bar-item> | /navigation-bar | value, hide-inactive-labels, icon, label, badge, active | | Navigation | <md-navigation-rail>, <md-navigation-rail-item> | /navigation-rail | value, alignment (top, center, bottom), hide-inactive-labels, icon, label, badge, active | | Navigation | <md-navigation-drawer>, <md-drawer> | /navigation-drawer | open, type (modal, standard, responsive), pivot (left, right), headline, responsive | | Navigation | <md-tabs>, <md-tab> | /tabs | active-index, icon, label, secondary | | Navigation | <md-menu>, <md-menu-item> | /menu | open, anchor, headline, icon, trailing-icon, shortcut, disabled, selected | | Navigation | <md-app-drawer>, <md-app-launcher> | /app-drawer | open, headline, icon, columns, reorderable, editable, modal, alignment, pivot | | Navigation | <md-account-menu>, <md-account-drawer> | /account-menu | open, name, email, avatar, initials, storage-used, storage-total, storage-progress, show-tabs, modal, alignment | | Media & Dev Tools | <md-code>, <md-code-block> | /code | code, language, filename, line-numbers, highlight-lines, lint, copyable, wrap-lines, max-height | | Media & Dev Tools | <md-player>, <md-media-player> | /player | type (audio, video), variant (elevated, filled, outlined, compact, full), src, track-title, artist, poster | | Internal Helpers | <md-ripple>, <md-focus-ring> | /ripple, /focus-ring | Interactive ripple effect & accessible WCAG focus indicator |


Usage Examples

Buttons, FABs & Icons

<!-- Buttons with 5 visual variants -->
<md-button variant="filled" icon="send">Send</md-button>
<md-button variant="elevated">Elevated</md-button>
<md-button variant="tonal">Tonal</md-button>
<md-button variant="outlined">Outlined</md-button>
<md-button variant="text">Text</md-button>

<!-- Loading State -->
<md-button variant="filled" loading>Saving...</md-button>

<!-- Icon Buttons (Standard, Filled, Tonal, Outlined, Toggle) -->
<md-icon-button icon="favorite" aria-label="Favorite"></md-icon-button>
<md-icon-button toggle icon="bookmark_border" selected-icon="bookmark" aria-label="Bookmark"></md-icon-button>

<!-- Floating Action Button -->
<md-fab icon="edit" label="Compose"></md-fab>
<md-fab size="small" icon="add" aria-label="Add"></md-fab>

<!-- Material Symbols Icon -->
<md-icon name="star" filled></md-icon>

Form Controls (Native Form Association)

All input components are Form-Associated Custom Elements (FACE) that natively integrate with standard <form> submission, reset, and FormData.

<form id="login-form">
  <md-text-field
    label="Full Name"
    name="name"
    required
    leading-icon="person"
    supporting-text="Your legal name"
  ></md-text-field>

  <md-text-field
    label="Email"
    name="email"
    type="email"
    required
    leading-icon="email"
  ></md-text-field>

  <md-checkbox name="newsletter" checked>
    Subscribe to newsletter
  </md-checkbox>

  <md-switch name="notifications" selected icons>
    Enable notifications
  </md-switch>

  <md-radio-group name="tier" value="pro">
    <md-radio value="free" label="Free"></md-radio>
    <md-radio value="pro" label="Pro"></md-radio>
  </md-radio-group>

  <div style="display: flex; gap: 8px; margin-top: 16px;">
    <md-button type="reset" variant="outlined">Reset</md-button>
    <md-button type="submit" variant="filled">Log In</md-button>
  </div>
</form>

Navigation & Top App Bar

<!-- Top App Bar -->
<md-top-app-bar variant="center-aligned" headline="My Application">
  <md-icon-button slot="navigation" icon="menu" aria-label="Open menu"></md-icon-button>
  <md-icon-button slot="actions" icon="search" aria-label="Search"></md-icon-button>
  <md-icon-button slot="actions" icon="account_circle" aria-label="Account"></md-icon-button>
</md-top-app-bar>

<!-- Navigation Drawer -->
<md-navigation-drawer headline="Navigation" type="modal" id="nav-drawer">
  <md-navigation-drawer-item icon="inbox" label="Inbox" badge="24" active></md-navigation-drawer-item>
  <md-navigation-drawer-item icon="send" label="Outbox"></md-navigation-drawer-item>
  <md-navigation-drawer-item icon="favorite" label="Favorites"></md-navigation-drawer-item>
  <md-navigation-drawer-item icon="settings" label="Settings"></md-navigation-drawer-item>
</md-navigation-drawer>

App Drawer & Account Menu

<!-- Google Apps style Launcher Grid -->
<md-app-drawer headline="Apps">
  <md-app-drawer-item icon="mail" label="Mail" badge="3"></md-app-drawer-item>
  <md-app-drawer-item icon="calendar_today" label="Calendar"></md-app-drawer-item>
  <md-app-drawer-item icon="folder" label="Drive"></md-app-drawer-item>
</md-app-drawer>

<!-- Account Menu & Switcher -->
<md-account-menu
  name="Franco Fantomius"
  email="[email protected]"
  initials="F"
  role-title="Lead Architect"
  organization="Material Components Team"
  storage-used="10.4 GB"
  storage-total="15 GB"
  storage-progress="0.69"
>
  <md-account-item slot="accounts" name="Franco Fantomius" email="[email protected]" initials="F" active></md-account-item>
  <md-account-item slot="accounts" name="Work Profile" email="[email protected]" initials="W"></md-account-item>
</md-account-menu>

Data Table

<md-table bordered striped hoverable id="my-table"></md-table>

<script>
  const table = document.getElementById('my-table');
  table.columns = [
    { key: 'name', label: 'User', sortable: true },
    { key: 'role', label: 'Role', sortable: true },
    { key: 'score', label: 'Score', numeric: true, sortable: true }
  ];
  table.rows = [
    { name: 'Alice Smith', role: 'Admin', score: 98 },
    { name: 'Bob Jones', role: 'Developer', score: 85 }
  ];
  table.selectable = true;
  table.paginated = true;
</script>

Search Bar with Live Suggestions

<md-search-bar placeholder="Search products..." id="search-bar" responsive></md-search-bar>

<script>
  const search = document.getElementById('search-bar');
  search.suggestions = [
    { label: 'Documentation', icon: 'description', supportingText: 'Getting started guide' },
    { label: 'Component Gallery', icon: 'widgets', supportingText: 'Explore all 23 components' }
  ];
  search.addEventListener('search', (e) => console.log('Query:', e.detail.value));
</script>

Code Block & Syntax Linter

<md-code
  language="typescript"
  filename="example.ts"
  line-numbers
  highlight-lines="2, 4-5"
  lint
  copyable
  code="const greeting: string = 'Hello, world!';\nconsole.log(greeting);"
></md-code>

Media Player (Audio & Video)

<!-- Audio Player -->
<md-player
  type="audio"
  src="https://example.com/audio.mp3"
  track-title="Ambient Soundscape"
  artist="Sound Design"
></md-player>

<!-- Video Player -->
<md-player
  type="video"
  src="https://example.com/video.mp4"
  poster="https://example.com/poster.jpg"
  track-title="Product Demo"
></md-player>

Form Integration (FACE)

Form elements (<md-text-field>, <md-checkbox>, <md-switch>, <md-radio>) use standard browser ElementInternals. They participate seamlessly in form life-cycles:

const form = document.getElementById('login-form');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  if (!form.checkValidity()) {
    form.reportValidity();
    return;
  }

  const formData = new FormData(form);
  console.log('Payload:', Object.fromEntries(formData.entries()));
});

Theming and Dark Mode

Dynamic Theming via CSS Custom Properties

The library uses standard Material Design 3 design tokens. Override them globally on :root or scope them to any container:

:root {
  --md-sys-color-primary: #6750A4;
  --md-sys-color-on-primary: #FFFFFF;
  --md-sys-color-primary-container: #EADDFF;
  --md-sys-color-on-primary-container: #21005D;
  --md-sys-color-surface: #FEF7FF;
  --md-sys-color-on-surface: #1D1B20;
}

[data-theme='dark'] {
  --md-sys-color-primary: #D0BCFF;
  --md-sys-color-on-primary: #381E72;
  --md-sys-color-primary-container: #4F378B;
  --md-sys-color-on-primary-container: #EADDFF;
  --md-sys-color-surface: #141218;
  --md-sys-color-on-surface: #E6E0E9;
}

TypeScript Theme Helper

import { applyTheme, darkColorScheme, lightColorScheme } from '@francofantomius/material-components/theme';

// Switch to dark theme
applyTheme(darkColorScheme);

// Switch back to light theme
applyTheme(lightColorScheme);

// Apply custom brand palette
applyTheme({
  primary: '#006A60',
  onPrimary: '#FFFFFF',
  primaryContainer: '#74F8E5',
  onPrimaryContainer: '#00201C',
});

Subpath Exports Reference

Each component can be imported individually with full TypeScript type definitions:

import { applyTheme } from '@francofantomius/material-components/theme';
import { MdButton } from '@francofantomius/material-components/button';
import { MdButtonGroup } from '@francofantomius/material-components/button-group';
import { MdSplitButton } from '@francofantomius/material-components/split-button';
import { MdSegmentedButton, MdSegmentedButtonSet } from '@francofantomius/material-components/segmented-button';
import { MdIconButton } from '@francofantomius/material-components/icon-button';
import { MdFab } from '@francofantomius/material-components/fab';
import { MdFabMenu, MdFabMenuItem } from '@francofantomius/material-components/fab-menu';
import { MdIcon } from '@francofantomius/material-components/icon';
import { MdToolbar } from '@francofantomius/material-components/toolbar';
import { MdTextField } from '@francofantomius/material-components/text-field';
import { MdCheckbox } from '@francofantomius/material-components/checkbox';
import { MdSwitch } from '@francofantomius/material-components/switch';
import { MdRadio, MdRadioGroup } from '@francofantomius/material-components/radio';
import { MdSlider } from '@francofantomius/material-components/slider';
import { MdDatePicker } from '@francofantomius/material-components/date-picker';
import { MdTimePicker } from '@francofantomius/material-components/time-picker';
import { MdChip, MdChipSet } from '@francofantomius/material-components/chip';
import { MdCard } from '@francofantomius/material-components/card';
import { MdDialog } from '@francofantomius/material-components/dialog';
import { MdSideSheet } from '@francofantomius/material-components/side-sheet';
import { MdBottomSheet } from '@francofantomius/material-components/bottom-sheet';
import { MdDivider } from '@francofantomius/material-components/divider';
import { MdProgress } from '@francofantomius/material-components/progress';
import { MdLoadingIndicator } from '@francofantomius/material-components/loading-indicator';
import { MdBadge } from '@francofantomius/material-components/badge';
import { MdSnackbar } from '@francofantomius/material-components/snackbar';
import { MdTooltip } from '@francofantomius/material-components/tooltip';
import { MdTabs, MdTab } from '@francofantomius/material-components/tabs';
import { MdList, MdListItem } from '@francofantomius/material-components/list';
import { MdMenu, MdMenuItem } from '@francofantomius/material-components/menu';
import { MdTopAppBar, MdTopBar } from '@francofantomius/material-components/top-app-bar';
import { MdNavigationBar, MdNavigationBarItem } from '@francofantomius/material-components/navigation-bar';
import { MdNavigationRail, MdNavigationRailItem } from '@francofantomius/material-components/navigation-rail';
import { MdNavigationDrawer, MdDrawer, MdMenuBar, MdNavigationDrawerItem } from '@francofantomius/material-components/navigation-drawer';
import { MdAppDrawer, MdAppDrawerItem, MdAppLauncher, MdAppsMenu } from '@francofantomius/material-components/app-drawer';
import { MdAccountMenu, MdAccountItem, MdAccountDrawer, MdAccountProfile } from '@francofantomius/material-components/account-menu';
import { MdTable, MdDataTable, MdTableHeaderCell, MdTableCell, MdTableRow } from '@francofantomius/material-components/table';
import { MdSearchBar, MdSearch } from '@francofantomius/material-components/search-bar';
import { MdCarousel, MdCarouselItem } from '@francofantomius/material-components/carousel';
import { MdCode, MdCodeBlock } from '@francofantomius/material-components/code';
import { MdPlayer, MdMediaPlayer, MdAudioPlayer, MdVideoPlayer } from '@francofantomius/material-components/player';

Framework Integration

Because Web Components are standard custom elements, they work natively across all frameworks:

React

React 19

React 19 supports Custom Elements natively (attributes, properties, and custom events):

import '@francofantomius/material-components/button';
import '@francofantomius/material-components/text-field';
import '@francofantomius/material-components/switch';

export function SettingsForm() {
  return (
    <div>
      <md-text-field
        label="Username"
        onInput={(e: any) => console.log(e.target.value)}
      />
      <md-switch
        selected
        onChange={(e: any) => console.log(e.target.selected)}
      >
        Enable Notifications
      </md-switch>
      <md-button variant="filled" onClick={() => alert('Saved!')}>
        Save
      </md-button>
    </div>
  );
}

React 18 / Next.js

In React 18, assign complex object/array properties (such as table.columns or search.suggestions) via React ref:

import React, { useRef, useEffect } from 'react';
import '@francofantomius/material-components/table';

export function UserTable({ users }) {
  const tableRef = useRef<any>(null);

  useEffect(() => {
    if (tableRef.current) {
      tableRef.current.columns = [
        { key: 'name', label: 'Name', sortable: true },
        { key: 'email', label: 'Email' }
      ];
      tableRef.current.rows = users;
    }
  }, [users]);

  return <md-table ref={tableRef} bordered hoverable />;
}

Vue

In Vue 3 / Nuxt, configure compiler options so Vue doesn't treat md-* elements as missing components:

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag.startsWith('md-')
        }
      }
    })
  ]
});
<script setup>
import { ref } from 'vue';
import '@francofantomius/material-components/button';
import '@francofantomius/material-components/switch';

const isEnabled = ref(true);
</script>

<template>
  <div>
    <md-switch :selected="isEnabled" @change="isEnabled = !isEnabled">
      Enable Feature
    </md-switch>
    <md-button variant="filled" :disabled="!isEnabled">
      Proceed
    </md-button>
  </div>
</template>

Angular

Include CUSTOM_ELEMENTS_SCHEMA in your standalone component or @NgModule:

import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@francofantomius/material-components/button';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `<md-button variant="filled">Click Me</md-button>`,
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent {}

Svelte

Custom elements work out-of-the-box with standard Svelte bindings:

<script>
  import '@francofantomius/material-components/button';
  import '@francofantomius/material-components/text-field';

  let name = '';
</script>

<md-text-field label="Name" value={name} on:input={(e) => name = e.target.value}></md-text-field>
<md-button variant="filled" on:click={() => alert(`Hello ${name}`)}>Submit</md-button>

LLM & AI Assistant Documentation

This repository provides an llms.txt file structured for AI coding assistants (such as Antigravity, Cursor, GitHub Copilot, ChatGPT, and Claude). It provides complete API specifications, component hierarchies, and ready-to-use code patterns.


Development Scripts

# Start local development playground & documentation
npm run dev

# Run unit tests with Vitest
npm test

# Type-check TypeScript codebase
npm run typecheck

# Build ESM library, docs & generate Custom Elements Manifest
npm run build

# Preview documentation site build
npm run preview

Automated Publishing (Trusted Publishing)

This repository is configured for npm Trusted Publishing using GitHub Actions OpenID Connect (OIDC).

How it works:

  1. When changes are merged to main, the CI workflow checks the version field in package.json.
  2. It queries npm to verify if this version is already published.
  3. If the version is new, it executes type checking, automated tests, builds the library, exchanges an OIDC token with npm, and publishes the package with cryptographic provenance (--provenance).
  4. It automatically creates a Git release and tag (v<version>).

License

MIT © francofantomius