nuclo 0.2.17 → 0.2.19
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 +29 -12
- package/package.json +2 -3
- package/types/features/render.d.ts +2 -1
- package/types/svg/base.d.ts +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# nuclo
|
|
2
2
|
|
|
3
|
-
**A lightweight,
|
|
3
|
+
**A lightweight, type-safe JS/TS DOM framework with plain mutable state and explicit updates.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Create elements with plain functions, and pass a function anywhere a value depends on state — that function is registered so Nuclo can evaluate it again later. Change regular JavaScript values directly, then call `update()` when you want Nuclo to synchronize the DOM. No virtual DOM, no proxies, no signals, and no automatic state tracking.
|
|
6
|
+
|
|
7
|
+
Nuclo's workflow has three parts:
|
|
8
|
+
|
|
9
|
+
1. **Create the UI with builder functions** — text, attributes, conditions, and lists can be passed a function whenever they depend on state; this registers the function as a state-dependent value.
|
|
10
|
+
2. **Mutate regular JavaScript state** — no signals, no proxies, no wrapped values. `count++` is just `count++`. Mutating state does not, by itself, touch the DOM.
|
|
11
|
+
3. **Call `update()`** — this explicitly starts synchronization: Nuclo reevaluates the state-dependent values registered in step 1 and applies changed results to the real DOM.
|
|
6
12
|
|
|
7
13
|
```ts
|
|
8
14
|
import 'nuclo';
|
|
@@ -22,12 +28,13 @@ render(counter, document.body);
|
|
|
22
28
|
|
|
23
29
|
## Why nuclo?
|
|
24
30
|
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
31
|
+
- **State-Dependent Values** – Pass a function for any text, attribute, condition, or list that depends on state; Nuclo can evaluate it again later
|
|
32
|
+
- **Explicit and Predictable** – Reevaluation doesn't happen on mutation — you trigger it yourself with a simple `update()` call
|
|
33
|
+
- **Real DOM, No Virtual Layer** – Nuclo creates and updates real DOM nodes directly; there's no virtual DOM to diff
|
|
34
|
+
- **Tiny Footprint** – ~13 KB gzipped, zero dependencies
|
|
28
35
|
- **Global Tag Builders** – Natural API with global functions for all HTML and SVG elements
|
|
29
36
|
- **TypeScript-First** – Full type definitions for all 175 HTML and SVG builders
|
|
30
|
-
- **Targeted DOM Updates** – `update()` re-runs
|
|
37
|
+
- **Targeted DOM Updates** – `update()` re-runs registered state-dependent values and only touches DOM where values changed
|
|
31
38
|
- **Atomic Styling** – Built-in `css()` / `createCss()` with TypeScript autocomplete, theming, and SSR CSS collection
|
|
32
39
|
- **Server-Side Rendering** – `renderToString()` + `hydrate()` with a lightweight DOM polyfill
|
|
33
40
|
|
|
@@ -303,6 +310,16 @@ render(app, document.body);
|
|
|
303
310
|
|
|
304
311
|
## Core Concepts
|
|
305
312
|
|
|
313
|
+
**The mental model:**
|
|
314
|
+
|
|
315
|
+
1. Create the UI with builder functions — `h1(...)`, `when()`, `list()`.
|
|
316
|
+
2. Use functions for values that depend on state — `h1(() => \`Count: ${count}\`)`. This registers a state-dependent value.
|
|
317
|
+
3. Mutate regular JavaScript state — `count++`.
|
|
318
|
+
4. Call `update()`.
|
|
319
|
+
5. Nuclo reevaluates the registered state-dependent values and applies the changes to the existing DOM.
|
|
320
|
+
|
|
321
|
+
State mutation and the `update()` call are plain JavaScript: you write `count++` and call `update()` yourself. Nuclo does not watch your variables — nothing reevaluates until `update()` runs. The function from step 2 stays registered so it can be evaluated again, but only `update()` starts that evaluation.
|
|
322
|
+
|
|
306
323
|
### 1. **Explicit Updates**
|
|
307
324
|
|
|
308
325
|
nuclo doesn't auto-detect changes. You call `update()` when ready:
|
|
@@ -344,7 +361,7 @@ user.name = 'Alice'; // triggers update
|
|
|
344
361
|
|
|
345
362
|
### 2. **Dynamic Functions**
|
|
346
363
|
|
|
347
|
-
Zero-arg functions become
|
|
364
|
+
Zero-arg functions become state-dependent values: Nuclo keeps them registered and can evaluate them again, but only when you call `update()` — mutating the state they read does nothing on its own:
|
|
348
365
|
|
|
349
366
|
```ts
|
|
350
367
|
let count = 0;
|
|
@@ -719,18 +736,18 @@ These markers identify conditional and list boundaries in the DOM.
|
|
|
719
736
|
### Gotchas
|
|
720
737
|
|
|
721
738
|
**Parameter count decides what a function modifier means.**
|
|
722
|
-
A modifier with **zero declared parameters** is treated as
|
|
739
|
+
A modifier with **zero declared parameters** is treated as dynamic text (or a dynamic `cn()` className) and is called with no arguments. A modifier with **one or more declared parameters** is a node-modifier function receiving `(element, index)`. Default and rest parameters don't count as declared parameters (`fn.length` is 0), so these are all treated as *dynamic text*, not node modifiers:
|
|
723
740
|
|
|
724
741
|
```ts
|
|
725
|
-
div((el = fallback) => el.id); //
|
|
726
|
-
div((...args) => args[0]); //
|
|
742
|
+
div((el = fallback) => el.id); // dynamic text — el is undefined!
|
|
743
|
+
div((...args) => args[0]); // dynamic text — args is empty!
|
|
727
744
|
div((el) => el.id = "x"); // node modifier — el is the element ✓
|
|
728
745
|
```
|
|
729
746
|
|
|
730
747
|
If a modifier needs the element, declare it as a plain required parameter.
|
|
731
748
|
|
|
732
|
-
**Detached nodes
|
|
733
|
-
|
|
749
|
+
**Detached nodes stop updating.**
|
|
750
|
+
Registered state-dependent values (text, attributes, `list()`, `when()`) are pruned for any node that is disconnected from the DOM when `update()` runs. Re-attaching the node later does **not** restore them. Keep-alive and portal-style patterns should rebuild content after re-attaching instead of moving live subtrees between updates.
|
|
734
751
|
|
|
735
752
|
---
|
|
736
753
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuclo",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.2.
|
|
5
|
-
"description": "Lightweight
|
|
4
|
+
"version": "0.2.19",
|
|
5
|
+
"description": "Lightweight, type-safe DOM library with plain mutable state and explicit updates — global tag builders, SSR, hydration, and atomic CSS, no virtual DOM, no compiler.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Danilo Celestino de Castro (https://github.com/dan2dev)",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"dom",
|
|
10
|
-
"reactive",
|
|
11
10
|
"ui",
|
|
12
11
|
"ssr",
|
|
13
12
|
"hydration",
|
|
@@ -26,7 +26,8 @@ declare global {
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Hydrates an existing server-rendered DOM tree by walking it in parallel with
|
|
29
|
-
* the component tree, reusing existing nodes and re-
|
|
29
|
+
* the component tree, reusing existing nodes and re-registering their
|
|
30
|
+
* state-dependent values for future `update()` calls.
|
|
30
31
|
*
|
|
31
32
|
* @param nodeModFn The NodeModFn to hydrate (same component used for SSR)
|
|
32
33
|
* @param parent The parent element containing the SSR HTML (defaults to document.body)
|
package/types/svg/base.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare global {
|
|
|
5
5
|
// SVG attribute types that accept string values for all SVG properties
|
|
6
6
|
// This is needed because SVG DOM properties like 'width' are SVGAnimatedLength,
|
|
7
7
|
// but we set them as strings using setAttribute()
|
|
8
|
-
// Supports
|
|
8
|
+
// Supports state-dependent values (functions) for dynamic attributes
|
|
9
9
|
export type SVGAttributes = {
|
|
10
10
|
// Common SVG attributes
|
|
11
11
|
width?: SVGAttributeValue<string | number>;
|
|
@@ -70,7 +70,7 @@ declare global {
|
|
|
70
70
|
"clip-path"?: SVGAttributeValue<string>;
|
|
71
71
|
mask?: SVGAttributeValue<string>;
|
|
72
72
|
|
|
73
|
-
// Allow any other string attributes (including
|
|
73
|
+
// Allow any other string attributes (including state-dependent functions)
|
|
74
74
|
// Using a more restrictive type to maintain type safety
|
|
75
75
|
} & {
|
|
76
76
|
[K in string]?: SVGAttributeValue;
|