eleva 1.0.0-rc.1 โ 1.0.0-rc.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +505 -41
- package/dist/eleva-plugins.cjs.js +3397 -0
- package/dist/eleva-plugins.cjs.js.map +1 -0
- package/dist/eleva-plugins.esm.js +3392 -0
- package/dist/eleva-plugins.esm.js.map +1 -0
- package/dist/eleva-plugins.umd.js +3403 -0
- package/dist/eleva-plugins.umd.js.map +1 -0
- package/dist/eleva-plugins.umd.min.js +3 -0
- package/dist/eleva-plugins.umd.min.js.map +1 -0
- package/dist/eleva.cjs.js +617 -118
- package/dist/eleva.cjs.js.map +1 -1
- package/dist/eleva.d.ts +612 -75
- package/dist/eleva.esm.js +617 -118
- package/dist/eleva.esm.js.map +1 -1
- package/dist/eleva.umd.js +617 -118
- package/dist/eleva.umd.js.map +1 -1
- package/dist/eleva.umd.min.js +2 -2
- package/dist/eleva.umd.min.js.map +1 -1
- package/dist/plugins/attr.umd.js +232 -0
- package/dist/plugins/attr.umd.js.map +1 -0
- package/dist/plugins/attr.umd.min.js +3 -0
- package/dist/plugins/attr.umd.min.js.map +1 -0
- package/dist/plugins/props.umd.js +712 -0
- package/dist/plugins/props.umd.js.map +1 -0
- package/dist/plugins/props.umd.min.js +3 -0
- package/dist/plugins/props.umd.min.js.map +1 -0
- package/dist/plugins/router.umd.js +1808 -0
- package/dist/plugins/router.umd.js.map +1 -0
- package/dist/plugins/router.umd.min.js +3 -0
- package/dist/plugins/router.umd.min.js.map +1 -0
- package/dist/plugins/store.umd.js +685 -0
- package/dist/plugins/store.umd.js.map +1 -0
- package/dist/plugins/store.umd.min.js +3 -0
- package/dist/plugins/store.umd.min.js.map +1 -0
- package/package.json +107 -45
- package/src/core/Eleva.js +247 -63
- package/src/modules/Emitter.js +98 -8
- package/src/modules/Renderer.js +66 -36
- package/src/modules/Signal.js +85 -8
- package/src/modules/TemplateEngine.js +121 -13
- package/src/plugins/Attr.js +255 -0
- package/src/plugins/Props.js +593 -0
- package/src/plugins/Router.js +1922 -0
- package/src/plugins/Store.js +744 -0
- package/src/plugins/index.js +40 -0
- package/types/core/Eleva.d.ts +217 -50
- package/types/core/Eleva.d.ts.map +1 -1
- package/types/modules/Emitter.d.ts +111 -12
- package/types/modules/Emitter.d.ts.map +1 -1
- package/types/modules/Renderer.d.ts +68 -3
- package/types/modules/Renderer.d.ts.map +1 -1
- package/types/modules/Signal.d.ts +92 -10
- package/types/modules/Signal.d.ts.map +1 -1
- package/types/modules/TemplateEngine.d.ts +131 -15
- package/types/modules/TemplateEngine.d.ts.map +1 -1
- package/types/plugins/Attr.d.ts +29 -0
- package/types/plugins/Attr.d.ts.map +1 -0
- package/types/plugins/Props.d.ts +49 -0
- package/types/plugins/Props.d.ts.map +1 -0
- package/types/plugins/Router.d.ts +1000 -0
- package/types/plugins/Router.d.ts.map +1 -0
- package/types/plugins/Store.d.ts +87 -0
- package/types/plugins/Store.d.ts.map +1 -0
- package/types/plugins/index.d.ts +5 -0
- package/types/plugins/index.d.ts.map +1 -0
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Eleva.js ๐
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Version:** `1.0.0-rc.11` | **Size:** ~6KB min (~2.5KB gzip) | **Dependencies:** Zero | **TypeScript:** Yes
|
|
4
|
+
|
|
5
|
+
**Best DX for Building the Best UX** โ Pure JavaScript, Pure Performance, Simply Elegant.
|
|
4
6
|
|
|
5
7
|
[](https://opensource.org/licenses/MIT)
|
|
6
8
|
[](https://github.com/TarekRaafat/eleva)
|
|
@@ -10,13 +12,13 @@ Pure JavaScript, Pure Performance, Simply Elegant.
|
|
|
10
12
|
[](https://codecov.io/gh/TarekRaafat/eleva)
|
|
11
13
|
[](https://bundlephobia.com/package/eleva@latest)
|
|
12
14
|
[](https://bundlephobia.com/package/eleva@latest)
|
|
13
|
-
[](https://www.jsdelivr.com/package/npm/eleva)
|
|
15
|
+
[](https://www.jsdelivr.com/package/npm/eleva)
|
|
14
16
|
[](https://canonical.com)
|
|
15
17
|
|
|
16
18
|
<br>
|
|
17
19
|
|
|
18
20
|
<p align="center">
|
|
19
|
-
<a href="https://tarekraafat.github.io/eleva/"><img src="./docs/imgs/eleva.js Full Logo.png" alt="
|
|
21
|
+
<a href="https://tarekraafat.github.io/eleva/"><img src="./docs/imgs/eleva.js Full Logo.png" alt="Eleva.js - Lightweight JavaScript Framework Logo" width="50%"></a>
|
|
20
22
|
</p>
|
|
21
23
|
|
|
22
24
|
<p align="center">
|
|
@@ -26,7 +28,7 @@ Pure JavaScript, Pure Performance, Simply Elegant.
|
|
|
26
28
|
</p>
|
|
27
29
|
|
|
28
30
|
<p align="center">
|
|
29
|
-
<em>Eleva
|
|
31
|
+
<em>Eleva is proudly supported by Canonical - the company behind Ubuntu.</em>
|
|
30
32
|
</p>
|
|
31
33
|
|
|
32
34
|
<p align="center">
|
|
@@ -37,12 +39,12 @@ Pure JavaScript, Pure Performance, Simply Elegant.
|
|
|
37
39
|
<br>
|
|
38
40
|
<br>
|
|
39
41
|
|
|
40
|
-
**A minimalist, lightweight, pure vanilla JavaScript frontend runtime framework.**
|
|
41
|
-
|
|
42
|
+
**A minimalist, lightweight, pure vanilla JavaScript frontend runtime framework.**
|
|
43
|
+
_Designed for the best Developer Experience (DX) to help you build exceptional User Experiences (UX). Built with love for native JavaScript and a minimal core that can be extended through a powerful plugin system โ because sometimes, less really is more!_ ๐
|
|
42
44
|
|
|
43
|
-
> **Stability Notice**: This is `v1.0.0-rc.
|
|
45
|
+
> **Stability Notice**: This is `v1.0.0-rc.11` - The core functionality is stable. Seeking community feedback before the final v1.0.0 release.
|
|
44
46
|
|
|
45
|
-
**Version:** `1.0.0-rc.
|
|
47
|
+
**Version:** `1.0.0-rc.11`
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
|
|
@@ -50,13 +52,30 @@ Welcome to Eleva! This is my humble, experimental playground for a fresh approac
|
|
|
50
52
|
|
|
51
53
|
---
|
|
52
54
|
|
|
55
|
+
## What is Eleva.js?
|
|
56
|
+
|
|
57
|
+
**Eleva** is a minimalist, lightweight (6KB), pure vanilla JavaScript frontend framework crafted for **exceptional Developer Experience (DX)**. When developers enjoy building, users enjoy using โ Eleva makes it effortless to create beautiful, responsive, and performant User Interfaces (UI) without the complexity, bundle size, or build tool requirements of traditional frameworks.
|
|
58
|
+
|
|
59
|
+
Unlike React, Vue, or Angular, Eleva:
|
|
60
|
+
- **Has zero dependencies** - No node_modules bloat
|
|
61
|
+
- **Requires no build step** - Works directly in browsers via CDN
|
|
62
|
+
- **Uses real DOM** - No virtual DOM overhead for simple apps
|
|
63
|
+
- **Provides signal-based reactivity** - Fine-grained updates like Solid.js
|
|
64
|
+
- **Includes TypeScript support** - Built-in type declarations
|
|
65
|
+
|
|
66
|
+
Eleva is ideal for developers building lightweight web applications, prototypes, micro-frontends, or anyone seeking a simpler alternative to React, Vue, or Angular.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
53
70
|
## Table of Contents
|
|
54
71
|
|
|
55
|
-
- [
|
|
72
|
+
- [Eleva.js ๐](#elevajs-)
|
|
73
|
+
- [What is Eleva.js?](#what-is-elevajs)
|
|
56
74
|
- [Table of Contents](#table-of-contents)
|
|
75
|
+
- [Quick Reference](#quick-reference)
|
|
57
76
|
- [Introduction](#introduction)
|
|
58
77
|
- [Design Philosophy](#design-philosophy)
|
|
59
|
-
- [
|
|
78
|
+
- [Best-in-Class Developer Experience (DX)](#best-in-class-developer-experience-dx)
|
|
60
79
|
- [Features](#features)
|
|
61
80
|
- [When to Use Eleva](#when-to-use-eleva)
|
|
62
81
|
- [Version Strategy](#version-strategy)
|
|
@@ -64,6 +83,7 @@ Welcome to Eleva! This is my humble, experimental playground for a fresh approac
|
|
|
64
83
|
- [Performance](#performance)
|
|
65
84
|
- [Performance Benchmarks](#performance-benchmarks)
|
|
66
85
|
- [Eleva vs. Popular Frameworks](#eleva-vs-popular-frameworks)
|
|
86
|
+
- [Browser Support](#browser-support)
|
|
67
87
|
- [Installation](#installation)
|
|
68
88
|
- [Usage](#usage)
|
|
69
89
|
- [ES Module Example](#es-module-example)
|
|
@@ -74,6 +94,12 @@ Welcome to Eleva! This is my humble, experimental playground for a fresh approac
|
|
|
74
94
|
- [Emitter](#emitter)
|
|
75
95
|
- [Renderer](#renderer)
|
|
76
96
|
- [Eleva (Core)](#eleva-core)
|
|
97
|
+
- [Plugins](#plugins)
|
|
98
|
+
- [Core Framework Only (Lightweight)](#core-framework-only-lightweight)
|
|
99
|
+
- [Attr Plugin](#attr-plugin)
|
|
100
|
+
- [Router Plugin](#router-plugin)
|
|
101
|
+
- [Props Plugin](#props-plugin)
|
|
102
|
+
- [Store Plugin](#store-plugin)
|
|
77
103
|
- [Development](#development)
|
|
78
104
|
- [Testing](#testing)
|
|
79
105
|
- [Contributing](#contributing)
|
|
@@ -82,17 +108,58 @@ Welcome to Eleva! This is my humble, experimental playground for a fresh approac
|
|
|
82
108
|
|
|
83
109
|
---
|
|
84
110
|
|
|
111
|
+
## Quick Reference
|
|
112
|
+
|
|
113
|
+
### Minimal Setup (30 seconds)
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
import Eleva from "eleva";
|
|
117
|
+
|
|
118
|
+
const app = new Eleva("MyApp");
|
|
119
|
+
|
|
120
|
+
app.component("Counter", {
|
|
121
|
+
setup: ({ signal }) => ({ count: signal(0) }),
|
|
122
|
+
template: (ctx) => `<button @click="() => count.value++">${ctx.count.value}</button>`
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
app.mount(document.getElementById("app"), "Counter");
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### API at a Glance
|
|
129
|
+
|
|
130
|
+
| Method | Purpose |
|
|
131
|
+
|--------|---------|
|
|
132
|
+
| `new Eleva(name)` | Create app |
|
|
133
|
+
| `app.component(name, def)` | Register component |
|
|
134
|
+
| `app.mount(el, name)` | Mount to DOM |
|
|
135
|
+
| `app.use(plugin)` | Add plugin |
|
|
136
|
+
| `signal(value)` | Reactive state |
|
|
137
|
+
| `emitter.on/emit` | Events |
|
|
138
|
+
|
|
139
|
+
### Template Syntax
|
|
140
|
+
|
|
141
|
+
> **Quick Rule:** `${}` needs `ctx.` โ `{{ }}` and `@events` don't.
|
|
142
|
+
|
|
143
|
+
| Syntax | Use | `ctx.`? |
|
|
144
|
+
|--------|-----|:-------:|
|
|
145
|
+
| `${expr}` | Static value | โ |
|
|
146
|
+
| `{{ expr }}` | Reactive value | โ |
|
|
147
|
+
| `@click` | Event handler | โ |
|
|
148
|
+
| `:prop` | Pass to child | โ |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
85
152
|
## Introduction
|
|
86
153
|
|
|
87
|
-
Eleva is a lightweight, no-nonsense runtime framework for frontend applications. Built with love for **pure vanilla JavaScript**, Eleva lets you create highly modular and scalable applications without the overhead of large frameworks. I built Eleva to prove that you don't need heavy frameworks or libraries to build amazing user interfaces-sometimes, the simplest approach is the most powerful.
|
|
154
|
+
Eleva is a lightweight, no-nonsense runtime framework for frontend applications. Built with love for **pure vanilla JavaScript**, Eleva features a minimal core with essential functionality that can be extended through a powerful plugin system. This approach lets you create highly modular and scalable applications without the overhead of large frameworks. I built Eleva to prove that you don't need heavy frameworks or libraries to build amazing user interfaces-sometimes, the simplest approach is the most powerful.
|
|
88
155
|
|
|
89
156
|
**My Inspiration:**
|
|
90
157
|
The idea behind Eleva comes from a deep appreciation for native JavaScript. I wanted to create a tool that stays true to the language without introducing new syntax or complexity, making it easy to integrate into your projects.
|
|
91
158
|
|
|
92
159
|
**Core Principles:**
|
|
93
160
|
|
|
94
|
-
- **๐ฑ Minimalism:** Only the
|
|
95
|
-
- **๐ Extensibility:**
|
|
161
|
+
- **๐ฑ Minimalism:** Only essential features in the core, keeping the framework lean and focused.
|
|
162
|
+
- **๐ Extensibility:** Extend functionality by plugging in your own ideas, such as custom state management, routing, and more.
|
|
96
163
|
- **๐ Performance:** Fast, efficient, and designed with modern browsers in mind.
|
|
97
164
|
- **๐ฆ Pure Vanilla:** No dependencies, no magic-just plain JavaScript.
|
|
98
165
|
|
|
@@ -100,9 +167,9 @@ The idea behind Eleva comes from a deep appreciation for native JavaScript. I wa
|
|
|
100
167
|
|
|
101
168
|
## Design Philosophy
|
|
102
169
|
|
|
103
|
-
**Eleva is an unopinionated framework.**
|
|
170
|
+
**Eleva is an unopinionated framework with a minimal core philosophy.**
|
|
104
171
|
|
|
105
|
-
Unlike
|
|
172
|
+
Unlike monolithic frameworks that include everything out-of-the-box, Eleva intentionally provides only essential features in its core, relying on a powerful plugin system for extensibility. This architectural choice means:
|
|
106
173
|
|
|
107
174
|
- **๐ Flexibility:** Architect your application your way-no rigid structure required.
|
|
108
175
|
- **๐ฏ Native JavaScript:** Built using pure vanilla JavaScript, Eleva integrates seamlessly with your existing code without unfamiliar syntax.
|
|
@@ -113,16 +180,27 @@ This unopinionated approach makes Eleva versatile and ideal for developers who w
|
|
|
113
180
|
|
|
114
181
|
---
|
|
115
182
|
|
|
116
|
-
##
|
|
183
|
+
## Best-in-Class Developer Experience (DX)
|
|
117
184
|
|
|
118
|
-
Eleva is built
|
|
185
|
+
Eleva is built on a simple principle: **great DX leads to great UX**. When developers have intuitive tools, they build better interfaces. Every aspect of Eleva's design prioritizes your productivity and enjoyment.
|
|
186
|
+
|
|
187
|
+
**Why Eleva's DX Stands Out:**
|
|
188
|
+
|
|
189
|
+
| DX Feature | How It Helps You Build Better UX |
|
|
190
|
+
|------------|----------------------------------|
|
|
191
|
+
| **Zero Config** | Start building immediately โ no webpack, no bundlers, no setup |
|
|
192
|
+
| **Intuitive API** | Learn in minutes, master in hours โ more time for polishing UI |
|
|
193
|
+
| **Pure JavaScript** | No JSX, no compilation โ what you write is what runs |
|
|
194
|
+
| **Instant Feedback** | Signal-based reactivity shows changes immediately |
|
|
195
|
+
| **TypeScript Built-in** | Full autocomplete and type safety out of the box |
|
|
196
|
+
| **Tiny Bundle** | ~2.5KB gzipped means instant page loads for your users |
|
|
119
197
|
|
|
120
198
|
- **๐จ Craftsmanship:** Every line of code is written with care, keeping the framework lightweight, efficient, and easy to understand.
|
|
121
|
-
- **๐ ๏ธ Developer-
|
|
122
|
-
- **๐
|
|
123
|
-
- **๐๏ธ
|
|
199
|
+
- **๐ ๏ธ Developer-First:** Intuitive API and minimal core mean you spend less time wrestling with the framework and more time perfecting your UI.
|
|
200
|
+
- **๐ No Magic:** Pure vanilla JavaScript with no hidden abstractions โ debug easily, ship confidently.
|
|
201
|
+
- **๐๏ธ Scales With You:** From prototype to production, Eleva grows with your project without added complexity.
|
|
124
202
|
|
|
125
|
-
|
|
203
|
+
> _"The best UX comes from developers who love their tools."_ โ Eleva's DX philosophy
|
|
126
204
|
|
|
127
205
|
---
|
|
128
206
|
|
|
@@ -136,6 +214,7 @@ This unique, developer-first approach makes Eleva a standout choice for building
|
|
|
136
214
|
- **๐ Lifecycle Hooks:** Complete lifecycle management with before/after mount and update hooks
|
|
137
215
|
- **๐งน Automatic Cleanup:** Proper cleanup of resources, watchers, and child components on unmount
|
|
138
216
|
- **๐ Plugin System:** Extensible architecture with a simple plugin API
|
|
217
|
+
- **๐ฏ Built-in Plugins:** Attr for advanced attributes, Props for complex data handling, Router for client-side routing, and Store for reactive state management
|
|
139
218
|
- **๐ฆ UMD & ES Module Builds:** Supports modern build tools and browser environments
|
|
140
219
|
- **๐ค Friendly API:** A gentle learning curve for both beginners and seasoned developers
|
|
141
220
|
- **๐ Tiny Footprint & TypeScript Support:** Approximately ~6 KB minified with built-in TypeScript declarations
|
|
@@ -152,6 +231,9 @@ Eleva is ideal for developers seeking a lightweight, flexible, and high-performa
|
|
|
152
231
|
- **๐ฏ Developer-Friendly:** Stick to pure vanilla JavaScript with familiar syntax and built-in TypeScript support.
|
|
153
232
|
- **๐งช Rapid Prototyping:** Quickly prototype ideas with a minimal and extendable framework.
|
|
154
233
|
- **๐ Extensible:** Easily add features like routing or state management through plugins.
|
|
234
|
+
- **๐ Built-in Routing:** Advanced client-side routing with navigation guards and reactive state via Router plugin.
|
|
235
|
+
- **๐ฏ Advanced Attributes:** Sophisticated attribute handling with ARIA support via Attr plugin.
|
|
236
|
+
- **๐ช Reactive State Management:** Centralized, reactive data store with persistence and namespacing via Store plugin.
|
|
155
237
|
- **๐ฆ Module Format Flexibility:** Choose from ESM, CommonJS, or UMD formats based on your project's needs.
|
|
156
238
|
|
|
157
239
|
---
|
|
@@ -160,9 +242,8 @@ Eleva is ideal for developers seeking a lightweight, flexible, and high-performa
|
|
|
160
242
|
|
|
161
243
|
I believe in clear versioning that reflects the maturity of the project:
|
|
162
244
|
|
|
163
|
-
- **Pre-release Versions (
|
|
245
|
+
- **Pre-release Versions (RC):** Release candidate versions like `1.0.0-rc.11` indicate the API is stable but still gathering community feedback before the final release.
|
|
164
246
|
- **Semantic Versioning:** Once stable, I'll follow semantic versioning strictly to clearly communicate any breaking changes.
|
|
165
|
-
- **Fresh Start:** This release (`1.2.0-alpha`) marks a significant update with enhanced inline documentation, improved JSDoc annotations, and a refined mounting context that now includes an `emitter` property.
|
|
166
247
|
|
|
167
248
|
---
|
|
168
249
|
|
|
@@ -181,7 +262,7 @@ I follow [Semantic Versioning (SemVer)](https://semver.org/):
|
|
|
181
262
|
|
|
182
263
|
Eleva is crafted for performance:
|
|
183
264
|
|
|
184
|
-
- **Lightweight:** Approximately ~6 KB minified and ~2 KB gzipped.
|
|
265
|
+
- **Lightweight:** Approximately ~6 KB minified and ~2.5 KB gzipped.
|
|
185
266
|
- **Efficient Reactivity:** Signal-based updates ensure only necessary DOM parts are updated.
|
|
186
267
|
- **Optimized Diffing:** Renderer efficiently patches changes without the overhead of a virtual DOM.
|
|
187
268
|
- **No Bloat:** Pure vanilla JavaScript with zero dependencies keeps your project nimble.
|
|
@@ -192,23 +273,50 @@ Eleva is crafted for performance:
|
|
|
192
273
|
|
|
193
274
|
## Performance Benchmarks
|
|
194
275
|
|
|
195
|
-
|
|
276
|
+
Benchmarks using [js-framework-benchmark](https://krausest.github.io/js-framework-benchmark/) methodology (1,000 rows):
|
|
277
|
+
|
|
278
|
+
| **Framework** | **Bundle Size (min+gzip)** | **Create 1K Rows** (ms) | **Partial Update** (ms) | **Memory** (MB) |
|
|
279
|
+
| ----------------------------- | -------------------------- | ----------------------- | ----------------------- | --------------- |
|
|
280
|
+
| **Eleva** (Direct DOM) | **~2.5 KB** | **~37** | ~97* | ~15 |
|
|
281
|
+
| **React 19** (Virtual DOM) | ~44 KB | 40-70 | 10-20 | 2-5 |
|
|
282
|
+
| **Vue 3.5** (Reactive) | ~35 KB | 25-45 | 5-15 | 2-4 |
|
|
283
|
+
| **Angular 19** (Signals) | ~90 KB | 50-80 | 15-25 | 3-6 |
|
|
196
284
|
|
|
197
|
-
|
|
198
|
-
| ----------------------------- | -------------------- | -------------------------- | ------------------------ | -------------------------- | ----------------------------------------------- |
|
|
199
|
-
| **Eleva** (Direct DOM) | **2** | **0.05** | **0.002** | **0.25** | **0.58 (Best)** |
|
|
200
|
-
| **React** (Virtual DOM) | 4.1 | 5.34 | 0.020 | 0.25 | 9.71 |
|
|
201
|
-
| **Vue** (Reactive State) | 45 | 4.72 | 0.021 | 3.10 | 13.21 |
|
|
202
|
-
| **Angular** (Two-way Binding) | 62 | 5.26 | 0.021 | 0.25 | 16.88 (Slowest) |
|
|
285
|
+
_*Eleva uses DOM diffing & patching, but templates generate HTML strings that require parsing. For large frequently-updating lists, use granular components or the `key` attribute for optimal diffing._
|
|
203
286
|
|
|
204
|
-
|
|
287
|
+
**Eleva's Strengths:**
|
|
288
|
+
- **Smallest bundle size** (~2.5 KB vs 35-90 KB)
|
|
289
|
+
- **Competitive initial render** (~37ms for 1K rows)
|
|
290
|
+
- **Zero dependencies** and minimal runtime overhead
|
|
291
|
+
- **Direct DOM diffing** without virtual DOM overhead
|
|
205
292
|
|
|
206
|
-
|
|
293
|
+
**Performance Tips:**
|
|
294
|
+
- Use `key` attribute on list items for optimal diffing
|
|
295
|
+
- Split large lists into smaller components
|
|
296
|
+
- Eleva excels at initial renders and small-to-medium updates
|
|
297
|
+
|
|
298
|
+
> ๐ก **Run benchmarks yourself:** `bun run test:benchmark`
|
|
299
|
+
|
|
300
|
+
> โ ๏ธ **Disclaimer:** Benchmarks vary by application complexity, browser, and hardware. Eleva results from internal test suite using Bun runtime. Other framework data from [js-framework-benchmark](https://krausest.github.io/js-framework-benchmark/).
|
|
207
301
|
|
|
208
302
|
---
|
|
209
303
|
|
|
210
304
|
## Eleva vs. Popular Frameworks
|
|
211
305
|
|
|
306
|
+
How does Eleva compare to popular JavaScript frameworks like React, Vue, Svelte, and Angular?
|
|
307
|
+
|
|
308
|
+
| Feature | Eleva | React | Vue | Svelte | Angular |
|
|
309
|
+
|---------|----------|-------|-----|--------|---------|
|
|
310
|
+
| **Bundle Size** | ~6KB | ~42KB | ~34KB | ~2.5KB* | ~130KB |
|
|
311
|
+
| **Dependencies** | 0 | 3+ | 0 | 0 | 10+ |
|
|
312
|
+
| **Virtual DOM** | No | Yes | Yes | No | No |
|
|
313
|
+
| **Reactivity** | Signals | useState/Hooks | Refs/Reactive | Compiler | Zone.js |
|
|
314
|
+
| **TypeScript** | Built-in | Optional | Optional | Built-in | Built-in |
|
|
315
|
+
| **Build Required** | No | Yes | Optional | Yes | Yes |
|
|
316
|
+
| **Learning Curve** | Low | Medium | Medium | Low | High |
|
|
317
|
+
|
|
318
|
+
_*Svelte compiles away, so runtime is minimal but build step is required._
|
|
319
|
+
|
|
212
320
|
Eleva offers a refreshing alternative to frameworks like React, Vue, and Angular:
|
|
213
321
|
|
|
214
322
|
- **Simplicity:** No virtual DOM, JSX, or complex state management-just plain JavaScript.
|
|
@@ -220,6 +328,26 @@ _Note:_ Eleva isn't trying to replace these giants but provides a lightweight op
|
|
|
220
328
|
|
|
221
329
|
---
|
|
222
330
|
|
|
331
|
+
## Browser Support
|
|
332
|
+
|
|
333
|
+
Eleva targets **modern evergreen browsers** and requires no polyfills.
|
|
334
|
+
|
|
335
|
+
| Browser | Minimum Version |
|
|
336
|
+
|---------|-----------------|
|
|
337
|
+
| Chrome | 71+ |
|
|
338
|
+
| Firefox | 69+ |
|
|
339
|
+
| Safari | 12.1+ |
|
|
340
|
+
| Edge | 79+ (Chromium) |
|
|
341
|
+
| iOS Safari | 12.2+ |
|
|
342
|
+
|
|
343
|
+
**Not Supported:** Internet Explorer, Legacy Edge (< 79)
|
|
344
|
+
|
|
345
|
+
**Why?** Eleva uses modern JavaScript features (`queueMicrotask`, ES6 Classes, async/await) to maintain its tiny footprint. These browsers cover **96%+ of global web traffic**.
|
|
346
|
+
|
|
347
|
+
> ๐ก For legacy browser support, use Babel with appropriate polyfills.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
223
351
|
## Installation
|
|
224
352
|
|
|
225
353
|
Eleva is available on npm. Try it out and share your thoughts!
|
|
@@ -267,10 +395,10 @@ app.component("HelloWorld", {
|
|
|
267
395
|
}
|
|
268
396
|
};
|
|
269
397
|
},
|
|
270
|
-
template: (
|
|
398
|
+
template: (ctx) => `
|
|
271
399
|
<div>
|
|
272
400
|
<h1>Hello, Eleva! ๐</h1>
|
|
273
|
-
<p>Count: ${count.value}</p>
|
|
401
|
+
<p>Count: ${ctx.count.value}</p>
|
|
274
402
|
<button @click="() => count.value++">Increment</button>
|
|
275
403
|
</div>
|
|
276
404
|
`
|
|
@@ -308,10 +436,10 @@ Include Eleva via a script tag and use the global variable:
|
|
|
308
436
|
const count = signal(0);
|
|
309
437
|
return { count };
|
|
310
438
|
},
|
|
311
|
-
template: (
|
|
439
|
+
template: (ctx) => `
|
|
312
440
|
<div>
|
|
313
441
|
<h1>Hello, Eleva! ๐</h1>
|
|
314
|
-
<p>Count: ${count.value}</p>
|
|
442
|
+
<p>Count: ${ctx.count.value}</p>
|
|
315
443
|
<button @click="() => count.value++">Increment</button>
|
|
316
444
|
</div>
|
|
317
445
|
`,
|
|
@@ -373,6 +501,332 @@ Interactive Demo: [CodePen](https://codepen.io/tarekraafat/pen/jEOyzYN?editors=1
|
|
|
373
501
|
- **`.mount(container, compName, props)`**
|
|
374
502
|
Mount a component to the DOM.
|
|
375
503
|
|
|
504
|
+
### Plugins
|
|
505
|
+
|
|
506
|
+
Eleva's plugin system allows you to extend functionality as needed. Plugins are **separately bundled** from the core framework, ensuring optimal tree-shaking and minimal bundle sizes.
|
|
507
|
+
|
|
508
|
+
**Plugin Types:**
|
|
509
|
+
|
|
510
|
+
| Type | Source | Installation |
|
|
511
|
+
|------|--------|--------------|
|
|
512
|
+
| **Core Plugins** | Bundled with Eleva | `import { X } from "eleva/plugins"` |
|
|
513
|
+
| **External Plugins** | Community/Ecosystem | `npm install eleva-plugin-x` |
|
|
514
|
+
|
|
515
|
+
> **Core plugins** (Attr, Props, Router, Store) are official, tested, and documented. **External plugins** are community-created and installed separately. See [Plugin Documentation](docs/plugins/index.md) for details.
|
|
516
|
+
|
|
517
|
+
#### Core Framework Only (Lightweight)
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
import Eleva from 'eleva';
|
|
521
|
+
|
|
522
|
+
const app = new Eleva("myApp");
|
|
523
|
+
// Core framework only - ~6KB minified
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
#### Attr Plugin
|
|
527
|
+
|
|
528
|
+
Advanced attribute handling for ARIA, data attributes, boolean properties, and dynamic property detection:
|
|
529
|
+
|
|
530
|
+
```javascript
|
|
531
|
+
import Eleva from 'eleva';
|
|
532
|
+
import { Attr } from 'eleva/plugins';
|
|
533
|
+
|
|
534
|
+
const app = new Eleva("myApp");
|
|
535
|
+
app.use(Attr, {
|
|
536
|
+
enableAria: true, // ARIA attribute handling
|
|
537
|
+
enableData: true, // Data attribute management
|
|
538
|
+
enableBoolean: true, // Boolean attribute processing
|
|
539
|
+
enableDynamic: true // Dynamic property detection
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
// Use advanced attributes in components
|
|
543
|
+
app.component("myComponent", {
|
|
544
|
+
template: (ctx) => `
|
|
545
|
+
<button
|
|
546
|
+
aria-expanded="${ctx.isExpanded.value}"
|
|
547
|
+
data-user-id="${ctx.userId.value}"
|
|
548
|
+
disabled="${ctx.isLoading.value}"
|
|
549
|
+
class="btn ${ctx.variant.value}"
|
|
550
|
+
>
|
|
551
|
+
${ctx.text.value}
|
|
552
|
+
</button>
|
|
553
|
+
`
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
๐ **[Full Attr Documentation โ](docs/plugins/attr.md)** - Comprehensive guide with ARIA attributes, data attributes, boolean handling, and dynamic properties.
|
|
558
|
+
|
|
559
|
+
#### Router Plugin
|
|
560
|
+
|
|
561
|
+
๐ **Advanced client-side routing** with multiple modes, navigation guards, reactive state, and component resolution:
|
|
562
|
+
|
|
563
|
+
```javascript
|
|
564
|
+
import Eleva from 'eleva';
|
|
565
|
+
import { Router } from 'eleva/plugins';
|
|
566
|
+
|
|
567
|
+
const app = new Eleva("myApp");
|
|
568
|
+
|
|
569
|
+
// Define components
|
|
570
|
+
const HomePage = { template: () => `<h1>Home</h1>` };
|
|
571
|
+
const AboutPage = { template: () => `<h1>About</h1>` };
|
|
572
|
+
const UserPage = {
|
|
573
|
+
template: (ctx) => `<h1>User: ${ctx.router.params.id}</h1>`
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
// Install router with advanced configuration
|
|
577
|
+
const router = app.use(Router, {
|
|
578
|
+
mount: '#app', // Mount element selector
|
|
579
|
+
mode: 'hash', // 'hash', 'history', or 'query'
|
|
580
|
+
routes: [
|
|
581
|
+
{
|
|
582
|
+
path: '/',
|
|
583
|
+
component: HomePage,
|
|
584
|
+
meta: { title: 'Home' }
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
path: '/about',
|
|
588
|
+
component: AboutPage,
|
|
589
|
+
beforeEnter: (to, from) => {
|
|
590
|
+
// Navigation guard
|
|
591
|
+
return true;
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
path: '/users/:id',
|
|
596
|
+
component: UserPage,
|
|
597
|
+
afterEnter: (to, from) => {
|
|
598
|
+
// Lifecycle hook
|
|
599
|
+
console.log('User page entered');
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
],
|
|
603
|
+
onBeforeEach: (to, from) => {
|
|
604
|
+
// Global navigation guard
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Access reactive router state
|
|
610
|
+
router.currentRoute.subscribe(route => {
|
|
611
|
+
console.log('Route changed:', route);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// Programmatic navigation
|
|
615
|
+
router.navigate('/users/123', { replace: true });
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
๐ **[Full Router Documentation โ](docs/plugins/router.md)** - Comprehensive guide with 13 events, 7 reactive signals, navigation guards, scroll management, and more.
|
|
619
|
+
|
|
620
|
+
#### Props Plugin
|
|
621
|
+
|
|
622
|
+
๐ฏ **Advanced props handling** with automatic type detection, parsing, and reactivity for complex data structures:
|
|
623
|
+
|
|
624
|
+
```javascript
|
|
625
|
+
import Eleva from 'eleva';
|
|
626
|
+
import { Props } from 'eleva/plugins';
|
|
627
|
+
|
|
628
|
+
const app = new Eleva("myApp");
|
|
629
|
+
app.use(Props, {
|
|
630
|
+
enableAutoParsing: true, // Enable automatic type detection
|
|
631
|
+
enableReactivity: true, // Enable reactive prop updates
|
|
632
|
+
onError: (error, value) => {
|
|
633
|
+
console.error('Props parsing error:', error, value);
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
// Use complex props in components
|
|
638
|
+
app.component("UserCard", {
|
|
639
|
+
template: (ctx) => `
|
|
640
|
+
<div class="user-container"
|
|
641
|
+
:user='${JSON.stringify(ctx.user.value)}'
|
|
642
|
+
:permissions='${JSON.stringify(ctx.permissions.value)}'>
|
|
643
|
+
</div>
|
|
644
|
+
`,
|
|
645
|
+
children: {
|
|
646
|
+
'.user-container': 'UserInfo'
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
app.component("UserInfo", {
|
|
651
|
+
setup({ props }) {
|
|
652
|
+
return {
|
|
653
|
+
user: props.user, // Automatically parsed object
|
|
654
|
+
permissions: props.permissions // Automatically parsed array
|
|
655
|
+
};
|
|
656
|
+
},
|
|
657
|
+
template: (ctx) => `
|
|
658
|
+
<div class="user-info">
|
|
659
|
+
<h3>${ctx.user.value.name}</h3>
|
|
660
|
+
<p>Role: ${ctx.user.value.role}</p>
|
|
661
|
+
</div>
|
|
662
|
+
`
|
|
663
|
+
});
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
๐ **[Full Props Documentation โ](docs/plugins/props.md)** - Comprehensive guide with type parsing, reactive props, signal linking, complex data structures, and error handling.
|
|
667
|
+
|
|
668
|
+
#### Store Plugin
|
|
669
|
+
|
|
670
|
+
๐ช **Reactive state management** with centralized data store, persistence, namespacing, and cross-component reactive updates:
|
|
671
|
+
|
|
672
|
+
```javascript
|
|
673
|
+
import Eleva from 'eleva';
|
|
674
|
+
import { Store } from 'eleva/plugins';
|
|
675
|
+
|
|
676
|
+
const app = new Eleva("myApp");
|
|
677
|
+
|
|
678
|
+
// Install store with configuration
|
|
679
|
+
app.use(Store, {
|
|
680
|
+
state: {
|
|
681
|
+
theme: "light",
|
|
682
|
+
counter: 0,
|
|
683
|
+
user: {
|
|
684
|
+
name: "John Doe",
|
|
685
|
+
email: "john@example.com"
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
actions: {
|
|
689
|
+
increment: (state) => state.counter.value++,
|
|
690
|
+
decrement: (state) => state.counter.value--,
|
|
691
|
+
toggleTheme: (state) => {
|
|
692
|
+
state.theme.value = state.theme.value === "light" ? "dark" : "light";
|
|
693
|
+
},
|
|
694
|
+
updateUser: (state, updates) => {
|
|
695
|
+
state.user.value = { ...state.user.value, ...updates };
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
// Optional: Namespaced modules
|
|
699
|
+
namespaces: {
|
|
700
|
+
auth: {
|
|
701
|
+
state: { token: null, isLoggedIn: false },
|
|
702
|
+
actions: {
|
|
703
|
+
login: (state, token) => {
|
|
704
|
+
state.auth.token.value = token;
|
|
705
|
+
state.auth.isLoggedIn.value = true;
|
|
706
|
+
},
|
|
707
|
+
logout: (state) => {
|
|
708
|
+
state.auth.token.value = null;
|
|
709
|
+
state.auth.isLoggedIn.value = false;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
},
|
|
714
|
+
// Optional: State persistence
|
|
715
|
+
persistence: {
|
|
716
|
+
enabled: true,
|
|
717
|
+
key: "myApp-store",
|
|
718
|
+
storage: "localStorage", // or "sessionStorage"
|
|
719
|
+
include: ["theme", "user"] // Only persist specific keys
|
|
720
|
+
}
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
// Use store in components
|
|
724
|
+
app.component("Counter", {
|
|
725
|
+
setup({ store }) {
|
|
726
|
+
return {
|
|
727
|
+
count: store.state.counter,
|
|
728
|
+
theme: store.state.theme,
|
|
729
|
+
increment: () => store.dispatch("increment"),
|
|
730
|
+
decrement: () => store.dispatch("decrement")
|
|
731
|
+
};
|
|
732
|
+
},
|
|
733
|
+
template: (ctx) => `
|
|
734
|
+
<div class="${ctx.theme.value}">
|
|
735
|
+
<h3>Counter: ${ctx.count.value}</h3>
|
|
736
|
+
<button @click="decrement">-</button>
|
|
737
|
+
<button @click="increment">+</button>
|
|
738
|
+
</div>
|
|
739
|
+
`
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
// Create state and actions at runtime
|
|
743
|
+
app.component("TodoManager", {
|
|
744
|
+
setup({ store }) {
|
|
745
|
+
// Register new module dynamically
|
|
746
|
+
store.registerModule("todos", {
|
|
747
|
+
state: { items: [], filter: "all" },
|
|
748
|
+
actions: {
|
|
749
|
+
addTodo: (state, text) => {
|
|
750
|
+
state.todos.items.value.push({
|
|
751
|
+
id: Date.now(),
|
|
752
|
+
text,
|
|
753
|
+
completed: false
|
|
754
|
+
});
|
|
755
|
+
},
|
|
756
|
+
toggleTodo: (state, id) => {
|
|
757
|
+
const todo = state.todos.items.value.find(t => t.id === id);
|
|
758
|
+
if (todo) todo.completed = !todo.completed;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// Create individual state properties
|
|
764
|
+
const notification = store.createState("notification", null);
|
|
765
|
+
|
|
766
|
+
// Create individual actions
|
|
767
|
+
store.createAction("showNotification", (state, message) => {
|
|
768
|
+
state.notification.value = message;
|
|
769
|
+
setTimeout(() => state.notification.value = null, 3000);
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
return {
|
|
773
|
+
todos: store.state.todos.items,
|
|
774
|
+
notification,
|
|
775
|
+
addTodo: (text) => store.dispatch("todos.addTodo", text),
|
|
776
|
+
notify: (msg) => store.dispatch("showNotification", msg)
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
// Subscribe to store changes
|
|
782
|
+
const unsubscribe = app.store.subscribe((mutation, state) => {
|
|
783
|
+
console.log('Store updated:', mutation.type, state);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// Access store globally
|
|
787
|
+
console.log(app.store.getState()); // Get current state values
|
|
788
|
+
app.dispatch("increment"); // Dispatch actions globally
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
๐ **[Full Store Documentation โ](docs/plugins/store.md)** - Comprehensive guide with 10 API methods, persistence options, namespaces, subscriptions, and migration guides.
|
|
792
|
+
|
|
793
|
+
**Bundle Sizes:**
|
|
794
|
+
- Core framework only: ~6KB (minified)
|
|
795
|
+
- Core + Attr: ~8KB (minified)
|
|
796
|
+
- Core + Props: ~10KB (minified)
|
|
797
|
+
- Core + Router: ~21KB (minified)
|
|
798
|
+
- Core + Store: ~12KB (minified)
|
|
799
|
+
- Core + All plugins: ~25KB (minified)
|
|
800
|
+
|
|
801
|
+
**Individual Plugin Sizes:**
|
|
802
|
+
- Attr: ~2.4KB (minified)
|
|
803
|
+
- Props: ~4.2KB (minified)
|
|
804
|
+
- Router: ~15KB (minified)
|
|
805
|
+
- Store: ~6KB (minified)
|
|
806
|
+
|
|
807
|
+
**Available Plugin Formats:**
|
|
808
|
+
|
|
809
|
+
**For Bundlers (Tree-Shaking Supported):**
|
|
810
|
+
- ESM: `import { Attr, Props, Router, Store } from 'eleva/plugins'`
|
|
811
|
+
- CJS: `const { Attr, Props, Router, Store } = require('eleva/plugins')`
|
|
812
|
+
|
|
813
|
+
**For CDN (Individual Plugins - Smaller Bundle Size):**
|
|
814
|
+
- UMD: `<script src="https://cdn.jsdelivr.net/npm/eleva@latest/dist/eleva.umd.min.js"></script>`
|
|
815
|
+
- UMD: `<script src="https://cdn.jsdelivr.net/npm/eleva@latest/dist/plugins/attr.umd.min.js"></script>`
|
|
816
|
+
- UMD: `<script src="https://cdn.jsdelivr.net/npm/eleva@latest/dist/plugins/props.umd.min.js"></script>`
|
|
817
|
+
- UMD: `<script src="https://cdn.jsdelivr.net/npm/eleva@latest/dist/plugins/router.umd.min.js"></script>`
|
|
818
|
+
- UMD: `<script src="https://cdn.jsdelivr.net/npm/eleva@latest/dist/plugins/store.umd.min.js"></script>`
|
|
819
|
+
|
|
820
|
+
**Individual Plugin Imports (Best for Tree-Shaking):**
|
|
821
|
+
- ESM: `import { Attr } from 'eleva/plugins/attr'`
|
|
822
|
+
- ESM: `import { Props } from 'eleva/plugins/props'`
|
|
823
|
+
- ESM: `import { Router } from 'eleva/plugins/router'`
|
|
824
|
+
- ESM: `import { Store } from 'eleva/plugins/store'`
|
|
825
|
+
- CJS: `const { Attr } = require('eleva/plugins/attr')`
|
|
826
|
+
- CJS: `const { Props } = require('eleva/plugins/props')`
|
|
827
|
+
- CJS: `const { Router } = require('eleva/plugins/router')`
|
|
828
|
+
- CJS: `const { Store } = require('eleva/plugins/store')`
|
|
829
|
+
|
|
376
830
|
For detailed API documentation, please check the [docs](docs/index.md) folder.
|
|
377
831
|
|
|
378
832
|
---
|
|
@@ -423,10 +877,20 @@ I welcome developers to dive in and experiment with Eleva! Here's how to get sta
|
|
|
423
877
|
|
|
424
878
|
## Testing
|
|
425
879
|
|
|
426
|
-
|
|
880
|
+
Eleva has a comprehensive test suite with **100% line coverage**:
|
|
881
|
+
|
|
882
|
+
| Metric | Value |
|
|
883
|
+
|--------|-------|
|
|
884
|
+
| **Total Tests** | 273 |
|
|
885
|
+
| **Line Coverage** | 100% |
|
|
886
|
+
| **Test Runner** | Bun |
|
|
887
|
+
|
|
888
|
+
Run the test suite:
|
|
427
889
|
|
|
428
890
|
```bash
|
|
429
|
-
|
|
891
|
+
bun test # Run all tests
|
|
892
|
+
bun test:coverage # Run with coverage report
|
|
893
|
+
bun test:benchmark # Run performance benchmarks
|
|
430
894
|
```
|
|
431
895
|
|
|
432
896
|
Contributions to tests are very welcome! ๐งช
|
|
@@ -453,7 +917,7 @@ Eleva is open-source and available under the [MIT License](LICENSE).
|
|
|
453
917
|
|
|
454
918
|
---
|
|
455
919
|
|
|
456
|
-
**Note:** This is a
|
|
920
|
+
**Note:** This is a release candidate (RC). The core functionality is stable and suitable for production use. Your feedback and contributions will help shape Eleva into something truly amazing. Let's build something great together! ๐ชโจ
|
|
457
921
|
|
|
458
922
|
---
|
|
459
923
|
|