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

@archtechx/alpine-reactive

v0.1.2

Published

Reactivity layer for Alpine 2.x

Readme

alpine-reactive

This package provides a reactivity layer for Alpine 2.x.

Problem

When you create a component that uses a value defined outside of it, you can modify the value from Alpine, but not vice versa:

<div x-data="{ counter: window.clickCount }">
    <button @click="counter++">+</button>
    Click count: <span x-text="count" />
    <button @click="counter++">--</button>
</div>

Clicking the buttons will update window.clickCount. However when window.clickCount is modified outside of the component, Alpine won't notice, and won't re-render the DOM.

Only after something else triggers a re-render, Alpine will show the correct click count again.

Solution

This package provides a reactive proxy wrapper for these objects. The syntax is very similar to Vue 3 — you just wrap the variable in reactive() and all changes will be tracked.

One difference between this package's solution and Vue's reactive() is that Alpine requires the calls to be component-specific. Meaning, the reactive() helper also needs the component instance/element. To simplify that, the package also provides a magic Alpine property, $reactive.

Installation

npm

npm install --save-dev @archtechx/alpine-reactive

Then import the library before importing Alpine:

import '@archtechx/alpine-reactive'

// import 'alpinejs'

To create reactive proxies, import the reactive helper:

import { reactive } from '@archtechx/alpine-reactive'

window.clickCounter = reactive({
    counter: 10,
})

The Alpine hook is executed automatically regardless of what parts of the library you import. For a full reference of the available helpers, see the Full API section below.

CDN

<script type="module">
    import { reactive } from 'https://unpkg.com/@archtechx/alpine-reactive'

    window.clickCounter = reactive({
        counter: 10,
    })

    // If you want to use reactive() outside of this script tag:
    // window.reactive = reactive
</script>

Demo

View online

<script>
    window.counter = reactive({
        count: 10,
    })
</script>

<div x-data="{ counter: $reactive(window.counter) }">
    <button @click="counter.count--">-</button>
    Click count: <span x-text="counter.count"></span>
    <button @click="counter.count++">+</button>
</div>

Under the hood, this creates a proxy that forwards everything to window.clickCount, but observes changes made to window.clickCount and updates the component as needed.

Of course, you may use the same reactive proxy in multiple components.

Full API

reactive(target, componentEl = null): Proxy for target

This creates a reactive proxy for object. If componentEl is passed, all writes to this proxy will trigger updateElements() on componentEl's Alpine instance.

ref(val): { value: val }

This turns foo into { value: foo }, which allows for foo — a primitive type in this example — to be used with proxies.

isRef(value): bool

Checks if a value is a ref.

unRef(value)

Syntactic sugar for isRef(value) ? value.value : value.

isReactiveProxy(proxy): bool

Checks whether the passed variable is a value returned by reactive().

watch(target, (key, value) => void) or watch(target, value => void), property)

Watches a reactive proxy, or a property on the reactive proxy.

Example:

watch(window.counter, (key, value) => console.log(`${key} was changed to ${value}`)); // Watch proxy
watch(window.counter, count => console.log(count), 'count'); // Watch property

Details

The package provides a $reactive magic property for Alpine. That property is syntactic sugar for reactive(target, $el).

- counter: reactive(window.counter, $el)
+ counter: $reactive(window.counter)

The magic property is added using the exported addMagicProperty() function, which is called once Alpine is available by the register() function. register() is called automatically for friendly CDN imports.