eleva

Store Plugin

Version: 1.0.0 Type: State Management Plugin Bundle Size: ~6KB minified Dependencies: Eleva core (Signal system)

The Store plugin provides centralized, reactive state management for Eleva applications. It enables sharing data across the entire application with automatic UI updates, action-based mutations, namespace organization, and built-in persistence.


TL;DR - Quick Reference

30-Second Setup

// file: app.js
import Eleva from "eleva";
import { Store } from "eleva/plugins";

const app = new Eleva("MyApp");

app.use(Store, {
  state: { count: 0 },
  actions: {
    increment: (state) => state.count.value++
  }
});

app.component("Counter", {
  setup({ store }) {
    return {
      count: store.state.count,
      increment: () => store.dispatch("increment")
    };
  },
  template: (ctx) => `
    <button @click="increment">Count: ${ctx.count.value}</button>
  `
});

app.mount(document.getElementById("app"), "Counter");
// Result: Button showing "Count: 0", increments on click

API Cheatsheet

Method Description Returns
store.state Reactive state object Object<Signal>
store.dispatch(action, payload?) Execute an action Promise<any>
store.subscribe(callback) Listen to all mutations () => void
store.getState() Get non-reactive snapshot Object
store.replaceState(newState) Replace entire state void
store.registerModule(name, module) Add dynamic module void
store.unregisterModule(name) Remove module void
store.createState(key, value) Add state property Signal
store.createAction(name, fn) Add action void
store.clearPersistedState() Clear storage void

State Access Patterns

Pattern Example
Read state store.state.count.value
In template ${ctx.count.value}
Namespaced state store.state.auth.user.value
Dispatch action store.dispatch("increment")
Dispatch with payload store.dispatch("setUser", { name: "John" })
Namespaced action store.dispatch("auth.login", credentials)

Configuration Quick Reference

app.use(Store, {
  state: { /* initial state */ },
  actions: { /* action functions */ },
  namespaces: { /* organized modules */ },
  persistence: {
    enabled: true,
    key: "app-store",
    storage: "localStorage",  // or "sessionStorage"
    include: ["theme"],       // only persist these
    exclude: ["tempData"]     // don't persist these
  },
  devTools: true,
  onError: (error, context) => console.error(error)
});

Template Context: Use ${ctx.count.value} in templates, but @click="increment" for events (no ctx.).


Documentation

Section Description
Core Concepts State, actions, and namespaces
Configuration Options, persistence, and DevTools
Usage Patterns Counter, todo list, auth, shopping cart
Advanced Dynamic modules, async patterns, complex state
API Reference Complete API, TypeScript, troubleshooting

Features

Feature Description
Reactive State State wrapped in Signals for automatic UI updates
Action-Based Mutations Predictable state changes with dispatch
Namespace Organization Modular state for large applications
Built-in Persistence Automatic localStorage/sessionStorage sync
Async Support Native async/await in actions
Subscriptions Listen to all state mutations
Dynamic Modules Register/unregister modules at runtime
DevTools Integration Debug state changes in development
TypeScript Support Full type definitions included

Installation

Via npm

npm install eleva
// ESM
import Eleva from "eleva";
import { Store } from "eleva/plugins";

// or individual import
import { Store } from "eleva/plugins/store";

Via CDN

<script src="https://cdn.jsdelivr.net/npm/eleva"></script>
<script src="https://cdn.jsdelivr.net/npm/eleva/dist/plugins/store.umd.min.js"></script>

<script>
  const app = new Eleva("MyApp");
  app.use(ElevaStore.Store, { /* options */ });
</script>

Basic Setup

// file: main.js
import Eleva from "eleva";
import { Store } from "eleva/plugins";

const app = new Eleva("MyApp");

// Install with initial state and actions
app.use(Store, {
  state: {
    theme: "light",
    user: null,
    counter: 0
  },
  actions: {
    setTheme: (state, theme) => state.theme.value = theme,
    setUser: (state, user) => state.user.value = user,
    increment: (state) => state.counter.value++,
    decrement: (state) => state.counter.value--
  }
});

Quick Start Example

import Eleva from "eleva";
import { Store } from "eleva/plugins";

const app = new Eleva("CounterApp");

app.use(Store, {
  state: { count: 0 },
  actions: {
    increment: (state) => state.count.value++,
    decrement: (state) => state.count.value--,
    reset: (state) => state.count.value = 0,
    setCount: (state, value) => state.count.value = value
  }
});

app.component("Counter", {
  setup({ store }) {
    return {
      count: store.state.count,
      increment: () => store.dispatch("increment"),
      decrement: () => store.dispatch("decrement"),
      reset: () => store.dispatch("reset")
    };
  },
  template: (ctx) => `
    <div class="counter">
      <h2>Count: ${ctx.count.value}</h2>
      <button @click="decrement">-</button>
      <button @click="reset">Reset</button>
      <button @click="increment">+</button>
    </div>
  `
});

app.mount(document.getElementById("app"), "Counter");
// Result: Interactive counter with increment, decrement, and reset

Data Flow

┌─────────────────────────────────────────────────────────────────┐
│                     STORE DATA FLOW                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────┐      ┌─────────────┐      ┌─────────────┐      │
│  │  Component  │      │  Component  │      │  Component  │      │
│  │      A      │      │      B      │      │      C      │      │
│  └──────┬──────┘      └──────┬──────┘      └──────┬──────┘      │
│         │                    │                    │             │
│         │   store.dispatch("action", payload)     │             │
│         └──────────────────┬──────────────────────┘             │
│                            │                                    │
│                            ▼                                    │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │                      STORE                              │    │
│  │  ┌─────────────────────────────────────────────────┐    │    │
│  │  │                    Actions                      │    │    │
│  │  │  increment: (state) => state.count.value++      │    │    │
│  │  └────────────────────┬────────────────────────────┘    │    │
│  │                       │                                 │    │
│  │                       ▼                                 │    │
│  │  ┌─────────────────────────────────────────────────┐    │    │
│  │  │                    State                        │    │    │
│  │  │  count: Signal(0)                               │    │    │
│  │  │  user: Signal(null)                             │    │    │
│  │  └────────────────────┬────────────────────────────┘    │    │
│  │                       │  Signal notifies watchers       │    │
│  │                       ▼                                 │    │
│  │  ┌─────────────────────────────────────────────────┐    │    │
│  │  │              Subscribers                        │    │    │
│  │  │  - Logging, Analytics, Persistence              │    │    │
│  │  └─────────────────────────────────────────────────┘    │    │
│  └─────────────────────────────────────────────────────────┘    │
│                            │                                    │
│         ┌──────────────────┼──────────────────┐                 │
│         ▼                  ▼                  ▼                 │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐          │
│  │  Component  │    │  Component  │    │  Component  │          │
│  │  A (update) │    │  B (update) │    │  C (update) │          │
│  └─────────────┘    └─────────────┘    └─────────────┘          │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Flow Description

  1. Component dispatches actionstore.dispatch("action", payload)
  2. Store executes action → Action function mutates state signals
  3. State signals notify → All watching components are notified
  4. Subscribers called → Logging, analytics, persistence run
  5. Components re-render → Only affected components update
  6. Persistence saves → If enabled, state is saved to storage

Next Steps


← Back to Plugins Next: Core Concepts →