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

@mschop/alpine-web-components

v2.0.1

Published

Use alpinejs with web components and shadow root

Readme

alpine-web-components

This library helps you with using AlpineJS with web components. This includes web components using shadow root.

Install

  1. Make sure you have AlpineJS installed and ready.
  2. Install this library by running npm i @mschop/alpine-web-components
  3. Use classes AlpineWebComponent or AlpineComponent as base classes.

How to use it

The following example shows you a basic "Counter" example.

import AlpineWebComponent from "alpine-shadow-component";
import type {State} from "../../AlpineWebComponent";

interface CounterState extends State {
    counter: number,
}

class Counter extends AlpineWebComponent {
    
    state: CounterState = {
        attributes: {},
        counter: 1,
    }
    
    template = `
        <span x-text=""></span>
        <button @click="counter++">+1</button>
        <button @click="component.resetCounter()">Reset</button>
    `
    
    resetCounter() {
        this.state.counter = 1
    }
    
    useShadow(): boolean {
        return false;
    }
}

window.customElements.define('my-counter', Counter);

You should now be able to reference the counter with <my-counter></my-counter>.

Note: Components are not automatically initialized. You need to call .init() on them. The common approach is to use x-init in the template:

<my-counter x-init="$el.init()"></my-counter>

The component instance is attached as state.component but marked raw, so Alpine won't proxy the full custom element. You can call component methods from the Alpine scope:

<button @click="component.resetCounter()">Reset</button>

Please see directory example for example on how to bind / update attributes etc..

Attribute-based state (string-only, isolated)

The default behavior mirrors component state to HTML attributes (and reads attributes back into state). This keeps the component interface purely declarative and works well for primitives (string/number/boolean).

Key points:

  • Attributes are always strings, so complex data must be serialized (e.g. JSON) via attributeCasts.
  • When state changes, the attribute is updated and an updated-<key> event is emitted.
  • When an attribute changes externally, the component state is updated.

This approach is useful when you want a clean HTML-only API and strict isolation between components. For complex data, consider property binding with x-init (see section above).

Passing complex data (avoid JSON in attributes)

Attributes are strings, so passing objects requires JSON encoding/decoding. If you want to share complex data (objects, arrays, reactive proxies) between components, bind a property instead of an attribute.

Alpine's x-init run once on init. So you can simply passing complex objects by passing the value in x-init.

<my-child x-init="
    $el.state.shared = parentState;
    $el.init();
"></my-child>

This keeps the template declarative while passing the actual object reference. Use attributes for primitives and properties for complex data.