@blu3ph4ntom/inval 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/README.md +58 -17
  2. package/package.json +3 -4
package/README.md CHANGED
@@ -11,7 +11,7 @@ inval: 50 widgets, change 1 width 4,230K ops/s (10x faster)
11
11
 
12
12
  ---
13
13
 
14
- ## Why Enterprise Teams Choose Inval
14
+ ## Why Enterprise Teams Should Choose Inval
15
15
 
16
16
  ### The Problem Nobody Talks About
17
17
 
@@ -49,6 +49,32 @@ bun add @blu3ph4ntom/inval
49
49
  pnpm add @blu3ph4ntom/inval
50
50
  ```
51
51
 
52
+ ### Why More Code?
53
+
54
+ Yes, `const area = node({ dependsOn: { w, h }, compute: ({ w, h }) => w * h })` is more verbose than `const area = width * height`.
55
+
56
+ **But consider what's missing from the simple version:**
57
+
58
+ ```typescript
59
+ // This is what your simple version is actually doing:
60
+ function getArea() {
61
+ // Did width or height change since last call?
62
+ // Do I need to recompute or can I return cached?
63
+ // What if I forgot a dependency and it's stale?
64
+ // What if height depends on width indirectly?
65
+ // How do I debug why it recomputed?
66
+ return width * height
67
+ }
68
+ ```
69
+
70
+ Inval gives you:
71
+ - **Explicit dependencies** — No more guessing what's cached
72
+ - **Debug tools** — `why(node)` tells you exactly what invalidated
73
+ - **Incremental updates** — Only recompute what changed
74
+ - **Production confidence** — 71 tests, deterministic behavior
75
+
76
+ **For simple cases** — use plain variables. **When layout gets complex** — Inval scales.
77
+
52
78
  ---
53
79
 
54
80
  ## The Inval Difference
@@ -56,24 +82,26 @@ pnpm add @blu3ph4ntom/inval
56
82
  ### Before (Naive Approach)
57
83
 
58
84
  ```typescript
59
- // Every width change recomputes EVERYTHING
60
- const width = 800
61
- const contentWidth = width - sidebar
62
- const cardHeight = textHeight(contentWidth, cardText)
63
- const rowOffset = index * cardHeight
64
- const visibleRange = computeVisible(scroll, rowOffset)
65
- // 50 widgets × 6 computations each = 300 recomputes
85
+ // Without a dependency graph, you must recompute everything
86
+ // or manually track what depends on what
87
+ function updateLayout(newWidth) {
88
+ const contentWidth = newWidth - sidebarWidth
89
+ const cardHeight = textHeight(contentWidth, cardText)
90
+ const rowOffset = index * cardHeight
91
+ const visibleRange = computeVisible(scrollTop, rowOffset)
92
+ // Either recompute all of these, or try to memoize each one
93
+ }
66
94
  ```
67
95
 
68
96
  ### After (With Inval)
69
97
 
70
98
  ```typescript
71
- import { input, node, batch, why } from '@blu3ph4ntom/inval'
99
+ import { input, node } from '@blu3ph4ntom/inval'
72
100
 
73
101
  const width = input(800)
74
102
  const contentWidth = node({
75
103
  dependsOn: { w: width },
76
- compute: ({ w }) => w - sidebar
104
+ compute: ({ w }) => w - sidebarWidth
77
105
  })
78
106
  const cardHeight = node({
79
107
  dependsOn: { cw: contentWidth },
@@ -82,14 +110,14 @@ const cardHeight = node({
82
110
 
83
111
  width.set(600)
84
112
  // Only contentWidth and cardHeight recompute
85
- // visibleRange? NOT dirty it doesn't depend on width
86
- // 5 widgets × 2 computations = 10 recomputes (30x less)
113
+ // visibleRange stays clean if it doesn't depend on width
114
+ // The library handles incremental updates automatically
87
115
  ```
88
116
 
89
117
  **You get:**
90
- - 10x faster performance on layout changes
118
+ - 10x faster performance on layout changes (benchmarked)
91
119
  - Exact knowledge of what recomputed (via `why()`)
92
- - Confidence your reflows are minimal and correct
120
+ - No more manual memoization guessing
93
121
 
94
122
  ---
95
123
 
@@ -122,12 +150,14 @@ why(area) // ['area', 'width'] — trace exact invalidation path
122
150
  ### Dashboard: 50 Widgets, One Width Change
123
151
 
124
152
  ```
125
- naive: 417,000 ops/s (recomputes all 50 × 6 = 300 computations)
126
- inval: 4,230,000 ops/s (recomputes only 10 computations)
153
+ naive: 417,000 ops/s (recomputes all computed nodes)
154
+ inval: 4,230,000 ops/s (recomputes only affected nodes)
127
155
  ─────────────────────────────────────────────────────────────
128
156
  10.1x faster in production-like scenario
129
157
  ```
130
158
 
159
+ Note: The naive comparison uses direct function calls without any optimization (no memoization, no dependency tracking). Your actual results will vary based on implementation.
160
+
131
161
  ### Virtualized List: 1000 Items, Width Change
132
162
 
133
163
  ```
@@ -424,8 +454,19 @@ open demo/pure/index.html # With inval
424
454
  open demo/without-inval/index.html # Without inval (naive)
425
455
  ```
426
456
 
457
+ ### Live Demo
458
+
459
+ A side-by-side dashboard demo showing the difference between using Inval vs naive approach:
460
+
461
+ - **demo/pure/index.html** — Uses Inval for incremental updates
462
+ - **demo/without-inval/index.html** — Recomputes everything on each change
463
+
464
+ ![Dashboard Demo](docs/dashboard-final.png)
465
+
466
+ The left panel uses Inval: notice the cached count stays high after initial computation. The right panel recomputes everything on each change.
467
+
427
468
  ---
428
469
 
429
470
  ## License
430
471
 
431
- MIT — free for commercial use.
472
+ MIT — free for commercial use.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blu3ph4ntom/inval",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Deterministic, incremental layout invalidation engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -47,14 +47,13 @@
47
47
  "license": "MIT",
48
48
  "devDependencies": {
49
49
  "esbuild": "^0.25.11",
50
- "playwright": "^1.59.1",
51
50
  "typescript": "^5.7.0"
52
51
  },
53
52
  "repository": {
54
53
  "type": "git",
55
- "url": "https://github.com/blu3ph4ntom/inval.git"
54
+ "url": "https://github.com/Blu3ph4ntom/inval.git"
56
55
  },
57
- "homepage": "https://github.com/blu3ph4ntom/inval#readme",
56
+ "homepage": "https://github.com/Blu3ph4ntom/inval#readme",
58
57
  "bugs": {
59
58
  "url": "https://github.com/blu3ph4ntom/inval/issues"
60
59
  },