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

alpinejs-component

v2.0.2

Published

Directive-based Alpine.js components with Shadow DOM encapsulation, slots, and cached template rendering

Readme

Alpine JS Component

Directive-based Alpine.js components with Shadow DOM encapsulation, slots, and cached template rendering.

✨ View the demos on CodePen

V2 Overview

v2 is directive-based and built around x-component.

  • No custom element registration required
  • Supports on-page templates and remote templates
  • Renders into Shadow DOM for style encapsulation
  • Supports default and named slots from host templates
  • Emits lifecycle events for loading, loaded, and error states
  • Uses bounded caches for templates, remote responses, and stylesheets

Install

With a CDN

<script
  defer
  src="https://unpkg.com/alpinejs-component@latest/dist/component.min.js"
></script>

<script defer src="https://unpkg.com/alpinejs@latest/dist/cdn.min.js"></script>

With a Package Manager

npm install alpinejs-component
yarn add alpinejs-component
pnpm add alpinejs-component
import Alpine from 'alpinejs'
import component from 'alpinejs-component'

Alpine.plugin(component)
Alpine.start()

Usage

v2 uses an Alpine directive: x-component.

Directive Reference

  • x-component="expression": render from an on-page <template id="...">
  • x-component.url="expression": render from a URL
  • x-component.url.external="expression": allow cross-origin http(s) URLs
  • x-component-styles="title-a,title-b": include matching document stylesheets
  • styles="...": alias for x-component-styles

The directive expression can be static or dynamic. Values are normalized as:

  • string: trimmed and used directly
  • number / boolean / other primitives: converted with String(...)
  • null / undefined / empty string: treated as empty source

When the resolved source is empty, the mounted component is unmounted/cleared.

Render From an On-Page Template

<div
  x-data="{
    people: [
      { name: 'John', age: '25', skills: ['JavaScript', 'CSS'] },
      { name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
    ]
  }"
>
  <ul>
    <template x-for="person in people" :key="person.name">
      <li>
        <div x-data="{ item: person }" x-component="'person-card'"></div>
      </li>
    </template>
  </ul>
</div>

<template id="person-card">
  <article>
    <h2 x-text="item.name"></h2>
    <p x-text="item.age"></p>

    <ul>
      <template x-for="skill in item.skills" :key="skill">
        <li x-text="skill"></li>
      </template>
    </ul>
  </article>
</template>

Render From a URL

Use the .url modifier when the expression resolves to a URL.

By default, .url only allows http(s) URLs on the current origin. Add the .external modifier to allow cross-origin http(s) URLs.

<div
  x-data="{
    people: [
      { name: 'John', age: '25', skills: ['JavaScript', 'CSS'] },
      { name: 'Jane', age: '30', skills: ['Laravel', 'MySQL', 'jQuery'] }
    ]
  }"
>
  <ul>
    <template x-for="person in people" :key="person.name">
      <li>
        <div
          x-data="{ item: person }"
          x-component.url="'/public/person-card.html'"
        ></div>
      </li>
    </template>
  </ul>
</div>

Dynamic Template Values

x-component and x-component.url support dynamic expressions.

<div
  x-data="{
    view: 'person-card',
    remoteView: '/public/person-card.html'
  }"
>
  <section x-component="view"></section>
  <section x-component.url="remoteView"></section>
</div>

Styles

Rendered component content is mounted in a Shadow DOM root.

Use x-component-styles (or styles) to include selected document stylesheets by title.

<style title="person-card">
  article {
    border: 1px solid #ddd;
  }
</style>

<div x-component="'person-card'" x-component-styles="person-card"></div>

Use global to include all local stylesheets:

<div x-component="'person-card'" x-component-styles="global"></div>

Slots

Slot templates can be declared on the host element with x-slot.

<div x-component="'card-with-slot'">
  <template x-slot>
    <p>Default slot content</p>
  </template>

  <template x-slot="actions">
    <button>Save</button>
  </template>
</div>

<template id="card-with-slot">
  <article>
    <slot></slot>
    <footer>
      <slot name="actions"></slot>
    </footer>
  </article>
</template>

Lifecycle Events

The host element emits lifecycle events:

  • x-component:loading when URL loading starts
  • x-component:loaded when render completes
  • x-component:error when expression evaluation, loading, or rendering fails

Event detail payloads:

  • x-component:loading: { source }
  • x-component:loaded: { source }
  • x-component:error: { source, error }

source is the resolved template id/URL for load/render failures, and the raw directive expression for expression-evaluation failures.

Evaluation failure behavior:

  • If directive expression evaluation throws, the plugin emits x-component:error with the evaluation error.
  • The component source is treated as empty, so any currently mounted content is cleared.
<div
  x-component.url="'/public/person-card.html'"
  x-on:x-component:loaded="console.log('component ready', $event.detail)"
  x-on:x-component:error="console.error('component failed', $event.detail)"
></div>

Security

Important: Only load templates from trusted sources. This plugin:

  • Renders HTML content directly (no sanitization)
  • Performs minimal URL validation (only http(s) and same-origin by default)
  • Is designed for developer-controlled content

Your responsibility:

  • Don't use user input directly in x-component or x-component.url
  • Only load templates from your own trusted servers
  • Validate/sanitize any dynamic template selection
  • Use CSP headers for additional protection
  • x-component.url accepts only http(s) URLs
  • x-component.url blocks cross-origin requests by default
  • Use x-component.url.external to opt into cross-origin http(s) requests

Browser Support

This plugin targets modern browsers with support for:

  • Shadow DOM
  • adoptedStyleSheets (when using x-component-styles / styles)
  • CSSStyleSheet (when using x-component-styles / styles)
  • template.content

If your target environment lacks these APIs, use a compatibility strategy or avoid Shadow DOM style adoption features.

Caching

The plugin maintains bounded in-memory caches:

  • Template fragments by template id (limit: 200)
  • Remote template fetch promises by normalized URL (limit: 200)
  • Adopted stylesheets by style target list (limit: 100)

When a cache exceeds its limit, oldest entries are evicted.

For URL mode, failed fetches are removed from cache so retries can succeed.

Development

npm install
npm run build

Available scripts:

  • npm run build: lint then build minified CDN + ESM outputs in dist/
  • npm run lint: run ESLint with --fix

Notes

  • Missing templates and failed URL requests are handled with console warnings/errors and lifecycle error events.
  • Expression evaluation failures dispatch x-component:error and clear mounted content for that host.
  • URL responses are cached by URL.
  • Template fragments are cached by template id.
  • Stylesheets are cached by style target list.

Migration From v1

v1:

<x-component template="person"></x-component>
<x-component url="/public/person.html"></x-component>

v2:

<div x-component="'person'"></div>
<div x-component.url="'/public/person.html'"></div>

window.xComponent.name custom-element renaming is no longer used because v2 is directive-based.