pulse-js-framework 1.2.0 → 1.4.1

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 CHANGED
@@ -1,245 +1,414 @@
1
- # Pulse Framework
2
-
3
- [![CI](https://github.com/vincenthirtz/pulse-js-framework/actions/workflows/ci.yml/badge.svg)](https://github.com/vincenthirtz/pulse-js-framework/actions/workflows/ci.yml)
4
- [![Netlify Status](https://api.netlify.com/api/v1/badges/2597dac2-228a-4d3e-bea8-4e7ef8ac5c53/deploy-status)](https://app.netlify.com/projects/pulse-js/deploys)
5
-
6
- A declarative DOM framework with CSS selector-based structure and reactive pulsations.
7
-
8
- ## Features
9
-
10
- - **CSS Selector Syntax** - Create DOM elements using familiar CSS selectors
11
- - **Reactive Pulsations** - Automatic UI updates when state changes
12
- - **Custom DSL** - Optional `.pulse` file format for cleaner code
13
- - **No Build Required** - Works directly in the browser
14
- - **Lightweight** - Minimal footprint, maximum performance
15
- - **Router & Store** - Built-in SPA routing and state management
16
- - **Mobile Apps** - Build native Android & iOS apps (zero dependencies)
17
-
18
- ## Installation
19
-
20
- ```bash
21
- npm install pulse-js-framework
22
- ```
23
-
24
- ## Quick Start
25
-
26
- ### Create a new project
27
-
28
- ```bash
29
- npx pulse create my-app
30
- cd my-app
31
- npm install
32
- npm run dev
33
- ```
34
-
35
- ### Or use directly
36
-
37
- ```javascript
38
- import { pulse, effect, el, mount } from 'pulse-js-framework';
39
-
40
- // Create reactive state
41
- const count = pulse(0);
42
-
43
- // Build UI with CSS selector syntax
44
- function Counter() {
45
- const div = el('.counter');
46
-
47
- const display = el('h1');
48
- effect(() => {
49
- display.textContent = `Count: ${count.get()}`;
50
- });
51
-
52
- const increment = el('button.btn', '+');
53
- increment.onclick = () => count.update(n => n + 1);
54
-
55
- const decrement = el('button.btn', '-');
56
- decrement.onclick = () => count.update(n => n - 1);
57
-
58
- div.append(display, increment, decrement);
59
- return div;
60
- }
61
-
62
- mount('#app', Counter());
63
- ```
64
-
65
- ## CSS Selector Syntax
66
-
67
- Create DOM elements using familiar CSS syntax:
68
-
69
- ```javascript
70
- el('div') // <div></div>
71
- el('.container') // <div class="container"></div>
72
- el('#app') // <div id="app"></div>
73
- el('button.btn.primary') // <button class="btn primary"></button>
74
- el('input[type=text]') // <input type="text">
75
- el('h1', 'Hello World') // <h1>Hello World</h1>
76
- ```
77
-
78
- ## Reactivity
79
-
80
- ```javascript
81
- import { pulse, effect, computed } from 'pulse-js-framework';
82
-
83
- // Create reactive values
84
- const firstName = pulse('John');
85
- const lastName = pulse('Doe');
86
-
87
- // Computed values
88
- const fullName = computed(() =>
89
- `${firstName.get()} ${lastName.get()}`
90
- );
91
-
92
- // Effects auto-run when dependencies change
93
- effect(() => {
94
- console.log(`Hello, ${fullName.get()}!`);
95
- });
96
-
97
- firstName.set('Jane'); // Logs: "Hello, Jane Doe!"
98
- ```
99
-
100
- ## .pulse File Format
101
-
102
- ```pulse
103
- @page Counter
104
-
105
- state {
106
- count: 0
107
- }
108
-
109
- view {
110
- .counter {
111
- h1 "Count: {count}"
112
- button @click(count++) "+"
113
- button @click(count--) "-"
114
- }
115
- }
116
-
117
- style {
118
- .counter {
119
- text-align: center
120
- padding: 20px
121
- }
122
- }
123
- ```
124
-
125
- ## API Reference
126
-
127
- ### Reactivity
128
-
129
- - `pulse(value)` - Create a reactive value
130
- - `pulse.get()` - Read value (tracks dependency)
131
- - `pulse.set(value)` - Set new value
132
- - `pulse.update(fn)` - Update with function
133
- - `pulse.peek()` - Read without tracking
134
- - `effect(fn)` - Create reactive side effect
135
- - `computed(fn)` - Create derived value
136
- - `batch(fn)` - Batch multiple updates
137
-
138
- ### DOM
139
-
140
- - `el(selector, ...children)` - Create element
141
- - `mount(target, element)` - Mount to DOM
142
- - `text(fn)` - Reactive text node
143
- - `list(items, template)` - Reactive list
144
- - `when(condition, then, else)` - Conditional render
145
-
146
- ### Router
147
-
148
- ```javascript
149
- import { createRouter } from 'pulse-js-framework/runtime/router.js';
150
-
151
- const router = createRouter({
152
- routes: {
153
- '/': HomePage,
154
- '/about': AboutPage,
155
- '/users/:id': UserPage
156
- }
157
- });
158
-
159
- router.start();
160
- ```
161
-
162
- ### Store
163
-
164
- ```javascript
165
- import { createStore } from 'pulse-js-framework/runtime/store.js';
166
-
167
- const store = createStore({
168
- user: null,
169
- theme: 'light'
170
- }, { persist: true });
171
-
172
- store.user.set({ name: 'John' });
173
- ```
174
-
175
- ## CLI Commands
176
-
177
- ```bash
178
- pulse create <name> # Create new project
179
- pulse dev [port] # Start dev server
180
- pulse build # Build for production
181
- pulse compile <file> # Compile .pulse file
182
- pulse mobile init # Initialize mobile platforms
183
- pulse mobile build android|ios # Build native app
184
- pulse mobile run android|ios # Run on device/emulator
185
- ```
186
-
187
- ## Mobile Apps
188
-
189
- Build native Android and iOS apps from your Pulse project with zero external dependencies:
190
-
191
- ```bash
192
- # Initialize mobile platforms
193
- pulse mobile init
194
-
195
- # Build your web app first
196
- pulse build
197
-
198
- # Build for Android (requires Android SDK)
199
- pulse mobile build android
200
-
201
- # Build for iOS (requires macOS + Xcode)
202
- pulse mobile build ios
203
-
204
- # Run on device/emulator
205
- pulse mobile run android
206
- ```
207
-
208
- ### Native APIs
209
-
210
- Access native features in your Pulse app:
211
-
212
- ```javascript
213
- import { createNativeStorage, NativeUI, onNativeReady } from 'pulse-js-framework/runtime/native';
214
-
215
- onNativeReady(({ platform }) => {
216
- console.log(`Running on ${platform}`); // 'android', 'ios', or 'web'
217
-
218
- // Persistent native storage with Pulse reactivity
219
- const storage = createNativeStorage();
220
- const count = storage.get('count', 0);
221
- count.set(42); // Auto-persisted to native storage
222
-
223
- // Native toast notification
224
- NativeUI.toast('Hello from Pulse!');
225
-
226
- // Haptic feedback
227
- NativeUI.vibrate(100);
228
- });
229
- ```
230
-
231
- **Available APIs:** Storage, Device Info, Network Status, Toast, Vibration, Clipboard, App Lifecycle
232
-
233
- ## Examples
234
-
235
- - [Todo App](examples/todo) - Task management with filters and persistence
236
- - [Chat App](examples/chat) - Real-time messaging interface
237
- - [E-commerce](examples/ecommerce) - Shopping cart with product catalog
238
- - [Weather App](examples/meteo) - Weather dashboard with forecasts
239
- - [Router Demo](examples/router) - SPA routing with guards
240
- - [Store Demo](examples/store) - State management with undo/redo
241
- - [Admin Dashboard](examples/dashboard) - Complete admin UI with all features
242
-
243
- ## License
244
-
245
- MIT
1
+ # Pulse Framework
2
+
3
+ [![CI](https://github.com/vincenthirtz/pulse-js-framework/actions/workflows/ci.yml/badge.svg)](https://github.com/vincenthirtz/pulse-js-framework/actions/workflows/ci.yml)
4
+ [![Netlify Status](https://api.netlify.com/api/v1/badges/2597dac2-228a-4d3e-bea8-4e7ef8ac5c53/deploy-status)](https://app.netlify.com/projects/pulse-js/deploys)
5
+
6
+ A declarative DOM framework with CSS selector-based structure and reactive pulsations.
7
+
8
+ ## Features
9
+
10
+ - **CSS Selector Syntax** - Create DOM elements using familiar CSS selectors
11
+ - **Reactive Pulsations** - Automatic UI updates when state changes
12
+ - **Custom DSL** - Optional `.pulse` file format for cleaner code
13
+ - **No Build Required** - Works directly in the browser
14
+ - **Lightweight** - Minimal footprint, maximum performance
15
+ - **Router & Store** - Built-in SPA routing and state management
16
+ - **Mobile Apps** - Build native Android & iOS apps (zero dependencies)
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install pulse-js-framework
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Create a new project
27
+
28
+ ```bash
29
+ npx pulse create my-app
30
+ cd my-app
31
+ npm install
32
+ npm run dev
33
+ ```
34
+
35
+ ### Or use directly
36
+
37
+ ```javascript
38
+ import { pulse, effect, el, mount } from 'pulse-js-framework';
39
+
40
+ // Create reactive state
41
+ const count = pulse(0);
42
+
43
+ // Build UI with CSS selector syntax
44
+ function Counter() {
45
+ const div = el('.counter');
46
+
47
+ const display = el('h1');
48
+ effect(() => {
49
+ display.textContent = `Count: ${count.get()}`;
50
+ });
51
+
52
+ const increment = el('button.btn', '+');
53
+ increment.onclick = () => count.update(n => n + 1);
54
+
55
+ const decrement = el('button.btn', '-');
56
+ decrement.onclick = () => count.update(n => n - 1);
57
+
58
+ div.append(display, increment, decrement);
59
+ return div;
60
+ }
61
+
62
+ mount('#app', Counter());
63
+ ```
64
+
65
+ ## CSS Selector Syntax
66
+
67
+ Create DOM elements using familiar CSS syntax:
68
+
69
+ ```javascript
70
+ el('div') // <div></div>
71
+ el('.container') // <div class="container"></div>
72
+ el('#app') // <div id="app"></div>
73
+ el('button.btn.primary') // <button class="btn primary"></button>
74
+ el('input[type=text]') // <input type="text">
75
+ el('h1', 'Hello World') // <h1>Hello World</h1>
76
+ ```
77
+
78
+ ## Reactivity
79
+
80
+ ```javascript
81
+ import { pulse, effect, computed } from 'pulse-js-framework';
82
+
83
+ // Create reactive values
84
+ const firstName = pulse('John');
85
+ const lastName = pulse('Doe');
86
+
87
+ // Computed values
88
+ const fullName = computed(() =>
89
+ `${firstName.get()} ${lastName.get()}`
90
+ );
91
+
92
+ // Effects auto-run when dependencies change
93
+ effect(() => {
94
+ console.log(`Hello, ${fullName.get()}!`);
95
+ });
96
+
97
+ firstName.set('Jane'); // Logs: "Hello, Jane Doe!"
98
+ ```
99
+
100
+ ## .pulse File Format
101
+
102
+ ```pulse
103
+ @page Counter
104
+
105
+ // Import other components
106
+ import Button from './Button.pulse'
107
+ import { Header, Footer } from './components.pulse'
108
+
109
+ state {
110
+ count: 0
111
+ }
112
+
113
+ view {
114
+ .counter {
115
+ Header
116
+ h1 "Count: {count}"
117
+ Button @click(count++) "+"
118
+ Button @click(count--) "-"
119
+ Footer
120
+ }
121
+ }
122
+
123
+ style {
124
+ .counter {
125
+ text-align: center
126
+ padding: 20px
127
+ }
128
+ }
129
+ ```
130
+
131
+ **Compiler Features:**
132
+ - Import statements for component composition
133
+ - Slots for content projection (`slot`, `slot "name"`)
134
+ - CSS scoping (styles are automatically scoped to component)
135
+ - Native `router {}` and `store {}` blocks
136
+ - Detailed error messages with line/column info
137
+
138
+ ### Router & Store DSL (v1.4.0)
139
+
140
+ Define routing and state management directly in your `.pulse` files:
141
+
142
+ ```pulse
143
+ @page App
144
+
145
+ router {
146
+ mode: "hash"
147
+ base: "/app"
148
+ routes {
149
+ "/": HomePage
150
+ "/users": UsersPage
151
+ "/users/:id": UserDetailPage
152
+ }
153
+ beforeEach(to, from) {
154
+ if (!store.isAuthenticated) return "/login"
155
+ }
156
+ }
157
+
158
+ store {
159
+ state {
160
+ user: null
161
+ theme: "dark"
162
+ }
163
+ getters {
164
+ isAuthenticated() { return this.user !== null }
165
+ }
166
+ actions {
167
+ login(userData) { this.user = userData }
168
+ logout() { this.user = null }
169
+ toggleTheme() { this.theme = this.theme === "dark" ? "light" : "dark" }
170
+ }
171
+ persist: true
172
+ storageKey: "my-app"
173
+ }
174
+
175
+ view {
176
+ .app {
177
+ nav {
178
+ @link("/") "Home"
179
+ @link("/users") "Users"
180
+ }
181
+ main {
182
+ @outlet
183
+ }
184
+ }
185
+ }
186
+ ```
187
+
188
+ **Router DSL Features:**
189
+ - Route definitions with path parameters (`:id`) and wildcards (`*path`)
190
+ - Navigation guards (`beforeEach`, `afterEach`)
191
+ - `@link("/path")` directive for navigation links
192
+ - `@outlet` directive for route content
193
+ - `@navigate`, `@back`, `@forward` directives
194
+
195
+ **Store DSL Features:**
196
+ - Reactive state with automatic signal creation
197
+ - Getters with `this.x` → `store.x.get()` transformation
198
+ - Actions with `this.x = y` → `store.x.set(y)` transformation
199
+ - Built-in persistence via `persist: true`
200
+ - Custom storage key
201
+
202
+ ## API Reference
203
+
204
+ ### Reactivity
205
+
206
+ - `pulse(value)` - Create a reactive value
207
+ - `pulse.get()` - Read value (tracks dependency)
208
+ - `pulse.set(value)` - Set new value
209
+ - `pulse.update(fn)` - Update with function
210
+ - `pulse.peek()` - Read without tracking
211
+ - `effect(fn)` - Create reactive side effect
212
+ - `computed(fn)` - Create derived value
213
+ - `batch(fn)` - Batch multiple updates
214
+
215
+ ### DOM
216
+
217
+ - `el(selector, ...children)` - Create element
218
+ - `mount(target, element)` - Mount to DOM
219
+ - `text(fn)` - Reactive text node
220
+ - `list(items, template)` - Reactive list
221
+ - `when(condition, then, else)` - Conditional render
222
+
223
+ ### Router
224
+
225
+ ```javascript
226
+ import { createRouter } from 'pulse-js-framework/runtime/router.js';
227
+
228
+ const router = createRouter({
229
+ routes: {
230
+ '/': HomePage,
231
+ '/about': AboutPage,
232
+ '/users/:id': UserPage,
233
+ '/admin': {
234
+ handler: AdminPage,
235
+ meta: { requiresAuth: true },
236
+ beforeEnter: (to, from) => {
237
+ if (!isAuthenticated()) return '/login';
238
+ },
239
+ children: {
240
+ '/users': AdminUsersPage,
241
+ '/settings': AdminSettingsPage
242
+ }
243
+ }
244
+ },
245
+ scrollBehavior: (to, from, savedPosition) => {
246
+ return savedPosition || { x: 0, y: 0 };
247
+ }
248
+ });
249
+
250
+ // Navigation guards
251
+ router.beforeEach((to, from) => {
252
+ if (to.meta.requiresAuth && !isAuthenticated()) {
253
+ return '/login';
254
+ }
255
+ });
256
+
257
+ router.start();
258
+ ```
259
+
260
+ **Router Features:**
261
+ - Route params (`:id`) and wildcards (`*path`)
262
+ - Nested routes with `children`
263
+ - Route meta fields
264
+ - Per-route guards (`beforeEnter`)
265
+ - Global guards (`beforeEach`, `beforeResolve`, `afterEach`)
266
+ - Scroll restoration
267
+ - Lazy-loaded routes (async handlers)
268
+
269
+ ### Store
270
+
271
+ ```javascript
272
+ import { createStore } from 'pulse-js-framework/runtime/store.js';
273
+
274
+ const store = createStore({
275
+ user: null,
276
+ theme: 'light'
277
+ }, { persist: true });
278
+
279
+ store.user.set({ name: 'John' });
280
+ ```
281
+
282
+ ## CLI Commands
283
+
284
+ ```bash
285
+ # Project Commands
286
+ pulse create <name> # Create new project
287
+ pulse dev [port] # Start dev server (default: 3000)
288
+ pulse build # Build for production
289
+ pulse preview [port] # Preview production build (default: 4173)
290
+ pulse compile <file> # Compile .pulse file to JavaScript
291
+
292
+ # Code Quality
293
+ pulse lint [files] # Validate .pulse files for errors and style
294
+ pulse lint --fix # Auto-fix fixable issues
295
+ pulse format [files] # Format .pulse files consistently
296
+ pulse format --check # Check formatting without writing
297
+ pulse analyze # Analyze bundle size and dependencies
298
+ pulse analyze --json # Output analysis as JSON
299
+
300
+ # Mobile
301
+ pulse mobile init # Initialize mobile platforms
302
+ pulse mobile build android|ios # Build native app
303
+ pulse mobile run android|ios # Run on device/emulator
304
+ ```
305
+
306
+ ### Lint Command
307
+
308
+ Validates `.pulse` files for errors and style issues:
309
+
310
+ ```bash
311
+ pulse lint src/ # Lint all files in src/
312
+ pulse lint "**/*.pulse" # Lint all .pulse files
313
+ pulse lint --fix # Auto-fix fixable issues
314
+ ```
315
+
316
+ **Checks performed:**
317
+ - Undefined references (state variables, components)
318
+ - Unused imports and state variables
319
+ - Naming conventions (PascalCase for pages, camelCase for state)
320
+ - Empty blocks
321
+ - Import order
322
+
323
+ ### Format Command
324
+
325
+ Formats `.pulse` files with consistent style:
326
+
327
+ ```bash
328
+ pulse format # Format all .pulse files
329
+ pulse format src/App.pulse # Format specific file
330
+ pulse format --check # Check without writing (CI mode)
331
+ ```
332
+
333
+ **Formatting rules:**
334
+ - 2-space indentation
335
+ - Sorted imports (alphabetically)
336
+ - Consistent brace placement
337
+ - Proper spacing around operators
338
+
339
+ ### Analyze Command
340
+
341
+ Analyzes your Pulse project for bundle insights:
342
+
343
+ ```bash
344
+ pulse analyze # Console report
345
+ pulse analyze --json # JSON output
346
+ pulse analyze --verbose # Detailed metrics
347
+ ```
348
+
349
+ **Analysis includes:**
350
+ - File count and total size
351
+ - Component complexity scores
352
+ - Import dependency graph
353
+ - Dead code detection (unreachable files)
354
+
355
+ ## Mobile Apps
356
+
357
+ Build native Android and iOS apps from your Pulse project with zero external dependencies:
358
+
359
+ ```bash
360
+ # Initialize mobile platforms
361
+ pulse mobile init
362
+
363
+ # Build your web app first
364
+ pulse build
365
+
366
+ # Build for Android (requires Android SDK)
367
+ pulse mobile build android
368
+
369
+ # Build for iOS (requires macOS + Xcode)
370
+ pulse mobile build ios
371
+
372
+ # Run on device/emulator
373
+ pulse mobile run android
374
+ ```
375
+
376
+ ### Native APIs
377
+
378
+ Access native features in your Pulse app:
379
+
380
+ ```javascript
381
+ import { createNativeStorage, NativeUI, onNativeReady } from 'pulse-js-framework/runtime/native';
382
+
383
+ onNativeReady(({ platform }) => {
384
+ console.log(`Running on ${platform}`); // 'android', 'ios', or 'web'
385
+
386
+ // Persistent native storage with Pulse reactivity
387
+ const storage = createNativeStorage();
388
+ const count = storage.get('count', 0);
389
+ count.set(42); // Auto-persisted to native storage
390
+
391
+ // Native toast notification
392
+ NativeUI.toast('Hello from Pulse!');
393
+
394
+ // Haptic feedback
395
+ NativeUI.vibrate(100);
396
+ });
397
+ ```
398
+
399
+ **Available APIs:** Storage, Device Info, Network Status, Toast, Vibration, Clipboard, App Lifecycle
400
+
401
+ ## Examples
402
+
403
+ - [Blog](examples/blog) - Full blog app with CRUD, categories, search, dark mode
404
+ - [Todo App](examples/todo) - Task management with filters and persistence
405
+ - [Chat App](examples/chat) - Real-time messaging interface
406
+ - [E-commerce](examples/ecommerce) - Shopping cart with product catalog
407
+ - [Weather App](examples/meteo) - Weather dashboard with forecasts
408
+ - [Router Demo](examples/router) - SPA routing with guards
409
+ - [Store Demo](examples/store) - State management with undo/redo
410
+ - [Admin Dashboard](examples/dashboard) - Complete admin UI with all features
411
+
412
+ ## License
413
+
414
+ MIT