nuclo 0.1.37 → 0.1.39
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 +77 -43
- package/package.json +14 -6
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# nuclo
|
|
2
2
|
|
|
3
|
-
**A DOM library for
|
|
3
|
+
**A simple, explicit DOM library for building reactive user interfaces.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Build reactive UIs without the magic tricks. Just functions, mutations, and a single `update()` call when you feel like it.
|
|
5
|
+
Build reactive UIs without the magic. Just functions, plain JavaScript objects, and explicit `update()` calls. No virtual DOM, no complex state management, no build configuration required.
|
|
8
6
|
|
|
9
7
|
```ts
|
|
10
8
|
import 'nuclo';
|
|
@@ -24,12 +22,12 @@ render(counter, document.body);
|
|
|
24
22
|
|
|
25
23
|
## Why nuclo?
|
|
26
24
|
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **Tiny
|
|
30
|
-
- **Global
|
|
31
|
-
- **TypeScript-
|
|
32
|
-
- **
|
|
25
|
+
- **Explicit and Predictable** – You control when updates happen with a simple `update()` call
|
|
26
|
+
- **Direct DOM Manipulation** – Work directly with the DOM, no virtual layer in between
|
|
27
|
+
- **Tiny Footprint** – Minimal bundle size, maximum performance
|
|
28
|
+
- **Global Tag Builders** – Natural API with global functions for all HTML and SVG elements
|
|
29
|
+
- **TypeScript-First** – Full type definitions for all 140+ HTML and SVG tags
|
|
30
|
+
- **Fine-Grained Reactivity** – Only updates what changed, nothing more
|
|
33
31
|
|
|
34
32
|
---
|
|
35
33
|
|
|
@@ -206,14 +204,17 @@ import 'nuclo';
|
|
|
206
204
|
type Product = { id: number; title: string; category: string };
|
|
207
205
|
type State = { status: 'idle' | 'loading' | 'error'; products: Product[]; error?: string };
|
|
208
206
|
|
|
209
|
-
|
|
207
|
+
const state: State = { status: 'idle', products: [] };
|
|
208
|
+
let searchQuery = 'phone';
|
|
210
209
|
|
|
211
210
|
async function fetchProducts() {
|
|
211
|
+
if (!searchQuery.trim()) return;
|
|
212
|
+
|
|
212
213
|
state.status = 'loading';
|
|
213
214
|
update();
|
|
214
215
|
|
|
215
216
|
try {
|
|
216
|
-
const response = await fetch(
|
|
217
|
+
const response = await fetch(`https://dummyjson.com/products/search?q=${searchQuery}`);
|
|
217
218
|
const data = await response.json();
|
|
218
219
|
state.products = data.products;
|
|
219
220
|
state.status = 'idle';
|
|
@@ -225,7 +226,21 @@ async function fetchProducts() {
|
|
|
225
226
|
}
|
|
226
227
|
|
|
227
228
|
const app = div(
|
|
228
|
-
|
|
229
|
+
div(
|
|
230
|
+
input(
|
|
231
|
+
{
|
|
232
|
+
type: 'search',
|
|
233
|
+
placeholder: 'Search products...',
|
|
234
|
+
value: () => searchQuery
|
|
235
|
+
},
|
|
236
|
+
on('input', e => {
|
|
237
|
+
searchQuery = e.target.value;
|
|
238
|
+
update();
|
|
239
|
+
}),
|
|
240
|
+
on('keydown', e => e.key === 'Enter' && fetchProducts())
|
|
241
|
+
),
|
|
242
|
+
button('Search', on('click', fetchProducts))
|
|
243
|
+
),
|
|
229
244
|
|
|
230
245
|
when(() => state.status === 'loading',
|
|
231
246
|
div('Loading...')
|
|
@@ -240,7 +255,7 @@ const app = div(
|
|
|
240
255
|
)
|
|
241
256
|
)
|
|
242
257
|
).else(
|
|
243
|
-
div('
|
|
258
|
+
div('Click search to load products')
|
|
244
259
|
)
|
|
245
260
|
);
|
|
246
261
|
|
|
@@ -253,7 +268,7 @@ render(app, document.body);
|
|
|
253
268
|
|
|
254
269
|
### 1. **Explicit Updates**
|
|
255
270
|
|
|
256
|
-
|
|
271
|
+
nuclo doesn't auto-detect changes. You call `update()` when ready:
|
|
257
272
|
|
|
258
273
|
```ts
|
|
259
274
|
let name = 'World';
|
|
@@ -268,11 +283,11 @@ update();
|
|
|
268
283
|
|
|
269
284
|
**Advantages of explicit `update()`:**
|
|
270
285
|
|
|
271
|
-
- **Performance**: Batch mutations
|
|
272
|
-
- **Control**: You
|
|
273
|
-
- **Predictability**: Zero surprise re-renders
|
|
274
|
-
- **Simplicity**: No proxies, no dependency graphs,
|
|
275
|
-
- **Debugging**:
|
|
286
|
+
- **Performance**: Batch multiple mutations into a single update cycle
|
|
287
|
+
- **Control**: You decide exactly when the UI should refresh
|
|
288
|
+
- **Predictability**: Zero surprise re-renders, explicit update flow
|
|
289
|
+
- **Simplicity**: No proxies, no dependency graphs, just objects and functions
|
|
290
|
+
- **Debugging**: Set a breakpoint at `update()` to trace all state changes
|
|
276
291
|
|
|
277
292
|
```ts
|
|
278
293
|
// Example: Batch updates for better performance
|
|
@@ -426,16 +441,16 @@ div({
|
|
|
426
441
|
|
|
427
442
|
### Batch Updates
|
|
428
443
|
|
|
429
|
-
|
|
444
|
+
Make multiple changes, then update once:
|
|
430
445
|
|
|
431
446
|
```ts
|
|
432
|
-
//
|
|
447
|
+
// Efficient: One update for all changes
|
|
433
448
|
items.push(item1);
|
|
434
449
|
items.push(item2);
|
|
435
450
|
items.sort();
|
|
436
451
|
update();
|
|
437
452
|
|
|
438
|
-
//
|
|
453
|
+
// Works but inefficient: Multiple updates
|
|
439
454
|
items.push(item1);
|
|
440
455
|
update();
|
|
441
456
|
items.push(item2);
|
|
@@ -444,14 +459,14 @@ update();
|
|
|
444
459
|
|
|
445
460
|
### Object Identity for Lists
|
|
446
461
|
|
|
447
|
-
Lists track items by reference. Mutate
|
|
462
|
+
Lists track items by reference. Mutate objects in place:
|
|
448
463
|
|
|
449
464
|
```ts
|
|
450
|
-
//
|
|
465
|
+
// Good: Mutate the object
|
|
451
466
|
todos[0].done = true;
|
|
452
467
|
update();
|
|
453
468
|
|
|
454
|
-
//
|
|
469
|
+
// Avoid: Creates new object, DOM element recreated
|
|
455
470
|
todos[0] = { ...todos[0], done: true };
|
|
456
471
|
update();
|
|
457
472
|
```
|
|
@@ -520,12 +535,12 @@ div(
|
|
|
520
535
|
|
|
521
536
|
## Performance
|
|
522
537
|
|
|
523
|
-
- **No virtual DOM diffing** –
|
|
524
|
-
- **Fine-grained updates** – Only updates what changed
|
|
525
|
-
- **Element reuse** – Lists
|
|
526
|
-
- **Branch preservation** –
|
|
538
|
+
- **No virtual DOM diffing** – Direct DOM manipulation for maximum efficiency
|
|
539
|
+
- **Fine-grained updates** – Only updates what changed, nothing more
|
|
540
|
+
- **Element reuse** – Lists intelligently reuse DOM elements when items move
|
|
541
|
+
- **Branch preservation** – Conditional branches persist until conditions change
|
|
527
542
|
|
|
528
|
-
For high-frequency updates (animations, game loops
|
|
543
|
+
For high-frequency updates (animations, game loops), batch mutations before calling `update()`.
|
|
529
544
|
|
|
530
545
|
---
|
|
531
546
|
|
|
@@ -533,7 +548,7 @@ For high-frequency updates (animations, game loops, existential crises), batch m
|
|
|
533
548
|
|
|
534
549
|
### Inspect Markers
|
|
535
550
|
|
|
536
|
-
Open DevTools
|
|
551
|
+
Open DevTools to see comment markers that help you understand the structure:
|
|
537
552
|
|
|
538
553
|
```html
|
|
539
554
|
<!-- when-start-1 -->
|
|
@@ -546,26 +561,45 @@ Open DevTools, stare at the DOM like it owes you money:
|
|
|
546
561
|
<!-- list-end -->
|
|
547
562
|
```
|
|
548
563
|
|
|
549
|
-
These
|
|
564
|
+
These markers identify conditional and list boundaries in the DOM.
|
|
550
565
|
|
|
551
566
|
### Common Issues
|
|
552
567
|
|
|
553
568
|
**Content not updating?**
|
|
554
|
-
-
|
|
555
|
-
-
|
|
569
|
+
- Ensure you're calling `update()` after state changes
|
|
570
|
+
- Verify your reactive functions are returning the expected values
|
|
556
571
|
|
|
557
572
|
**List items not reusing elements?**
|
|
558
|
-
-
|
|
559
|
-
-
|
|
573
|
+
- Keep object references stable (mutate instead of replacing)
|
|
574
|
+
- Avoid creating new objects when updating properties
|
|
560
575
|
|
|
561
576
|
---
|
|
562
577
|
|
|
563
578
|
## Roadmap
|
|
564
579
|
|
|
565
|
-
- Keyed list variant
|
|
566
|
-
- Transition
|
|
567
|
-
- Dev mode diagnostics
|
|
568
|
-
-
|
|
580
|
+
- Keyed list variant for explicit key-based tracking
|
|
581
|
+
- Transition and animation helpers
|
|
582
|
+
- Dev mode diagnostics and warnings
|
|
583
|
+
- Server-side rendering (SSR) support
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## Documentation
|
|
588
|
+
|
|
589
|
+
Full documentation is available at [https://dan2dev.github.io/nuclo/](https://dan2dev.github.io/nuclo/)
|
|
590
|
+
|
|
591
|
+
- [Getting Started](https://dan2dev.github.io/nuclo/getting-started.html)
|
|
592
|
+
- [API Reference](https://dan2dev.github.io/nuclo/api.html)
|
|
593
|
+
- [Examples](https://dan2dev.github.io/nuclo/examples.html)
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
## Author
|
|
598
|
+
|
|
599
|
+
Created by **Danilo Celestino de Castro**
|
|
600
|
+
|
|
601
|
+
- GitHub: [@dan2dev](https://github.com/dan2dev)
|
|
602
|
+
- Twitter: [@dan2dev](https://twitter.com/dan2dev)
|
|
569
603
|
|
|
570
604
|
---
|
|
571
605
|
|
|
@@ -573,6 +607,6 @@ These comment markers are your breadcrumbs. Follow them to victory.
|
|
|
573
607
|
|
|
574
608
|
MIT License - see [LICENSE.md](LICENSE.md) for details.
|
|
575
609
|
|
|
576
|
-
This library is free and open source. When using nuclo, please include attribution in your documentation
|
|
610
|
+
This library is free and open source. When using nuclo, please include attribution in your documentation or application.
|
|
577
611
|
|
|
578
|
-
**TL;DR:** Use it freely,
|
|
612
|
+
**TL;DR:** Use it freely, give credit where it's due!
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuclo",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.39",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/nuclo.cjs",
|
|
7
7
|
"module": "./dist/nuclo.js",
|
|
@@ -22,14 +22,21 @@
|
|
|
22
22
|
"types"
|
|
23
23
|
],
|
|
24
24
|
"devDependencies": {
|
|
25
|
+
"@eslint/css": "^0.14.0",
|
|
26
|
+
"@eslint/js": "^9.39.0",
|
|
27
|
+
"@eslint/json": "^0.13.2",
|
|
28
|
+
"@eslint/markdown": "^7.5.0",
|
|
25
29
|
"@rollup/plugin-terser": "^0.4.4",
|
|
26
|
-
"@rollup/plugin-typescript": "^12.
|
|
27
|
-
"@types/node": "^24.
|
|
30
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
31
|
+
"@types/node": "^24.9.2",
|
|
28
32
|
"@vitest/coverage-v8": "3.2.4",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
33
|
+
"eslint": "^9.39.0",
|
|
34
|
+
"globals": "^16.4.0",
|
|
35
|
+
"jsdom": "^27.1.0",
|
|
36
|
+
"rollup": "^4.52.5",
|
|
31
37
|
"tslib": "^2.8.1",
|
|
32
38
|
"typescript": "^5.9.3",
|
|
39
|
+
"typescript-eslint": "^8.46.2",
|
|
33
40
|
"vitest": "^3.2.4"
|
|
34
41
|
},
|
|
35
42
|
"repository": {
|
|
@@ -49,6 +56,7 @@
|
|
|
49
56
|
"build:types": "tsc --emitDeclarationOnly",
|
|
50
57
|
"clean": "rm -rf dist *.tsbuildinfo",
|
|
51
58
|
"test": "vitest run --coverage",
|
|
52
|
-
"test:watch": "vitest --watch"
|
|
59
|
+
"test:watch": "vitest --watch",
|
|
60
|
+
"lint": "eslint . --ext .ts,.js,.json,.jsonc,.json5,.md,.css"
|
|
53
61
|
}
|
|
54
62
|
}
|