lightview 2.2.1 → 2.3.4

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/cDOMIntro.md ADDED
@@ -0,0 +1,279 @@
1
+ # The Future of AI-Generated UI: Why I Built cDOM and JPRX
2
+
3
+ **A declarative, secure, and reactive approach to let both humans and LLMs build rich user interfaces.**
4
+
5
+ ---
6
+
7
+ ## The Problem with AI-Generated Interfaces
8
+
9
+ We are at an inflection point in software development. Large Language Models (LLMs) are rapidly evolving from text-generation tools into full-fledged software agents capable of building applications, analyzing data, and interacting with users in real-time. But there's a critical bottleneck: **how do these agents communicate visually with humans?**
10
+
11
+ The traditional options are bleak:
12
+ 1. **Text-Only Responses**: The chatbot experience. Great for conversation, terrible for complex interactions. Ever tried to book a flight through a wall of text? It's exhausting.
13
+ 2. **Raw Code Generation (HTML/JS/React)**: The agent spits out code, and you hope it works. This is a **massive security risk**. Arbitrary code execution is the original sin of computing—do you really want to `eval()` whatever a cloud-based AI model sends you? The answer is no. And, the flexibility of raw language generation can result in either too much brittle code or too much variance from UI exprience to UI experience, something humans do not handle well.
14
+ The end states are far away:
15
+ 1. **Direct generation of images and video** with which users can interact in real-time is too expensive and slow.
16
+ 2. **Direct mind interfaces** are not yet possible except for the simplest of tasks.
17
+
18
+ Google recognized the traditional options gap or and perhaps the distance to an ultimate end-state and introduced **A2UI (Agent-to-User Interface)** in late 2025. It's a declarative JSON format where agents describe UI components like `text_field` or `button`, and client applications render them natively. It's a solid approach with a security-first architecture.
19
+
20
+ But I asked a additional questions:
21
+
22
+ * **Why just *describe* the UI? Why not make it *reactive* by design?**
23
+ * **Why limit this approach to LLMs?** Why not provide a reactive, cross-platform way for *human developers* to safely express UIs too?
24
+
25
+ This is why I built **cDOM (Computational DOM)** and its expression language, **JPRX (JSON Pointer Reactive eXpressions)**.
26
+
27
+ Let me show you how it works, step by step.
28
+
29
+ ---
30
+
31
+ ## Step 1: A Reactive UI with Zero Server Code or Custom JavaScript
32
+
33
+ Consider a simple counter. In cDOM, you write this:
34
+
35
+ ```json
36
+ {
37
+ "div": {
38
+ "onmount": "=state({ count: 0 }, { name: 'local', scope: $this })",
39
+ "children": [
40
+ { "p": ["Count: ", "=local/count"] },
41
+ { "button": { "onclick": "=local/count++", "children": ["+"] } }
42
+ ]
43
+ }
44
+ }
45
+ ```
46
+
47
+ That's it. No server. No round-trip. No JavaScript except the underlying cDOM library (which could be JavaScript, Dart or some other language).
48
+
49
+ * The `state` helper initializes reactive state (`{ count: 0 }`) scoped to this element.
50
+ * The `=local/count` expression is a **live binding**—the paragraph text updates automatically whenever `count` changes.
51
+ * The `=local/count++` operator is a direct increment.
52
+
53
+ The entire UI is reactive, self-contained, and runs instantly in the browser.
54
+
55
+ **This is the spreadsheet paradigm applied to UI**: you define the relationships, and the system handles the updates. JPRX has **over 100** helper functions, covering everything from math and string manipulation to complex array processing and lookup logic, e.g. sum, min, max, sort, filter, etc.
56
+
57
+ ---
58
+
59
+ ## Step 2: But What If You *Do* Want LLM Integration?
60
+
61
+ The counter example is great for client-only interactions. But what if you want to notify an LLM (or any server) when the user clicks a button?
62
+
63
+ Just swap the operator for a `=fetch` helper:
64
+
65
+ ```json
66
+ {
67
+ "button": {
68
+ "onclick": "=fetch('/api/notify', { method: 'POST', body: $event })",
69
+ "children": ["Notify LLM"]
70
+ }
71
+ }
72
+ ```
73
+
74
+ When the button is clicked:
75
+ 1. The `=fetch` helper sends a POST request to `/api/notify` with a JSON body.
76
+ 2. Object bodies are automatically stringified, and `Content-Type: application/json` is set for you.
77
+ 3. The LLM (or your backend) receives the event and can respond however it likes.
78
+
79
+ This is the **event registration model**: the LLM doesn't need to be notified of *every* interaction. It only hears about the events that matter—the ones where you've wired up a `fetch`. Developers can wire up `fetch` to any event they want, or when LLMs generate a cDOM component, they can wire up `fetch` to notify them of specific user actions.
80
+
81
+ This avoids the potential chatty nature of A2UI. Do you really want the LLM notified of every mouse move? Keyboard stroke? Scroll position? If it time and cost effective to have an LLM deal with things like sorting and filtering, or should you let the client handle it?
82
+
83
+ ---
84
+
85
+ ## Step 3: What If the LLM Wants to *Modify* the UI?
86
+
87
+ Here's where cDOM gets truly powerful. What if the server (or LLM) wants to push a new component into the page?
88
+
89
+ Enter `=mount`:
90
+
91
+ ```json
92
+ {
93
+ "button": {
94
+ "onclick": "=mount('/api/get-widget')",
95
+ "children": ["Load Widget"]
96
+ }
97
+ }
98
+ ```
99
+
100
+ When clicked, `mount` fetches JSON from `/api/get-widget`, hydrates it as a reactive cDOM element, and **appends it to the document body**.
101
+
102
+ But wait, what if the LLM wants to place that widget somewhere specific, like a sidebar? That's where `move` comes in.
103
+
104
+ The LLM simply includes a `=move` directive in the component it returns:
105
+
106
+ ```json
107
+ {
108
+ "div": {
109
+ "id": "weather-widget",
110
+ "onmount": "=move('#dashboard-sidebar', 'afterbegin')",
111
+ "children": ["Sunny, 75°F"]
112
+ }
113
+ }
114
+ ```
115
+
116
+ Here's what happens:
117
+ 1. `mount` fetches the widget and appends it to the `body` (a "safe landing").
118
+ 2. The moment the widget mounts, `move` **rips it out** and **teleports** it to `#dashboard-sidebar`.
119
+ 3. If a widget with the same `id` already exists there, it's **replaced** - making the operation idempotent.
120
+
121
+ **The LLM doesn't need to regenerate the entire page.** It just pushes components that know how to place themselves.
122
+
123
+ ---
124
+
125
+ ## The Full Picture: Three Levels of Power
126
+
127
+ You've now seen the three core capabilities:
128
+
129
+ | Level | Use Case | Helper | Server Involved? |
130
+ |-------|-----------------------------------|----------------------|------------------|
131
+ | 1 | Client-only reactivity | `=state`, `=++`, etc | ❌ No |
132
+ | 2 | Notify LLM of user actions | `=fetch` | ✅ Yes (one-way) |
133
+ | 3 | LLM pushes new UI to the client | `=mount`, `=move` | ✅ Yes (returns UI)|
134
+
135
+ This layered approach means you can build:
136
+ * Fully offline-capable apps (Level 1)
137
+ * Hybrid apps where the LLM is notified selectively (Level 2)
138
+ * Agent-driven apps where the LLM controls the UI in real-time (Level 3)
139
+
140
+ All with the same declarative JSON format.
141
+
142
+ ---
143
+
144
+ ## JPRX: The Expression Language Behind the Magic
145
+
146
+ You've been looking at JPRX expressions this whole time. Let me explain what's under the hood.
147
+
148
+ **JPRX (JSON Pointer Reactive eXpressions)** is an extension of RFC 6901 JSON Pointer. It adds:
149
+
150
+ * **Expressions**: Any path or function name beginning with `=` is an expression. Only the first expression of a nested expression needs to start with `=`.
151
+ * **Reactivity**: Any path starting with `=` (e.g., `=app/user/name`) creates a live subscription. When the data changes, so does the UI.
152
+ * **Operators**: Prefix and postfix mutation (`=++/count`, `=count--`, `=!!/enabled`).
153
+ * **Helper Functions**: Over 100 Excel-like functions (`sum`, `if`, `upper`, `filter`, `map`, `formatDate`) plus state-mutating helpers (`set`, `push`, `assign`), e.g. `=set(/app/user/name, 'John Doe')`.
154
+ * **Relative Paths**: Use `../` to navigate up context hierarchies, just like a file system.
155
+
156
+ Why is this perfect for LLMs?
157
+ 1. **Context-Free Grammar**: No closures, no callbacks. An LLM generates JPRX as easily as it generates a sentence.
158
+ 2. **Safe by Design**: No access to `globalThis`, `eval`, or the DOM API outside registered helpers. The application developer controls the helper catalog.
159
+ 3. **Streamable**: The LLM can stream components one by one. Each piece is self-describing and self-mounting.
160
+
161
+ And why is it great for human developers? Because JPRX reads like a spreadsheet formula. If you can write `=SUM(A1:A10)`, you can write `=sum(/cart/items...price)`.
162
+
163
+ ---
164
+
165
+ ## The Chattiness Trade-Off
166
+
167
+ A key difference between cDOM and A2UI is how user interactions are handled.
168
+
169
+ In A2UI, the interaction follows a continuous loop:
170
+ 1. **Agent emits** a UI description.
171
+ 2. **Client renders** it.
172
+ 3. **User interacts** (clicks a button).
173
+ 4. **Client signals** the action back to the agent.
174
+ 5. **Agent reasons** and emits a new UI.
175
+
176
+ This is architecturally clean and ensures the agent is always the "brain" of the operation. However, it can become **chatty**. When every interaction requires a network round-trip, latency and bandwidth usage can accumulate, potentially affecting the user experience.
177
+
178
+ More importantly, it creates an **over-reliance on the LLM for trivial tasks**. Does an agent really need to "reason" about how to sort a list of five items alphabetically? Or how to toggle a "Show Details" pane?
179
+
180
+ cDOM flips this model. Event handlers are JPRX expressions that execute **client-side**. The user clicks "+", the count increments *locally*. The user clicks "Sort", the list reorders instantly in the browser.
181
+
182
+ If the LLM *does* need to know about a significant interaction, you explicitly wire up a `fetch`. But routine UI logic stays where it belongs: on the client.
183
+
184
+ **LLM-driven architecture. Native-like responsiveness.**
185
+
186
+ ---
187
+
188
+ ## Head-to-Head: cDOM vs. A2UI
189
+
190
+ | Feature | cDOM/JPRX (Lightview) | A2UI (Google) |
191
+ |--------------------------------|------------------------------------------------------------|-----------------------------------------------------------|
192
+ | **Core Paradigm** | Declarative + Reactive Computation | Declarative Description |
193
+ | **Client-Side Reactivity** | ✅ Built-in via signals & computed expressions | ❌ Requires server round-trip for state changes |
194
+ | **Interaction Model** | ✅ Handlers execute client-side (low latency) | ⚠️ Every interaction signals back to agent (chatty) |
195
+ | **Security Model** | ✅ Sandboxed helper functions, no arbitrary code | ✅ Sandboxed component catalog, no arbitrary code |
196
+ | **Expression Language** | ✅ Full formula language with 100+ helpers | ❌ Data binding only, no computation in the format |
197
+ | **LLM Streaming** | ✅ Components self-mount & teleport via `=move` | ✅ Flat component list with IDs for incremental updates |
198
+ | **Two-Way Binding** | ✅ `=bind(/path)` for inputs, selects, checkboxes | ⚠️ Component-specific, varies by renderer |
199
+ | **State Management** | ✅ Scoped, schema-validated `state` objects | ❌ External state managed by agent or backend |
200
+ | **Framework** | Lightview (Vanilla JS, ~5KB core) | Client-agnostic (Flutter, React, Angular renderers) |
201
+
202
+ A2UI is an excellent wire format for describing **static snapshots** of a UI. It fits neatly into enterprise ecosystems where Flutter or Angular applications render components.
203
+
204
+ cDOM is designed for **dynamic, client-reactive applications** where the UI is a living computation. When your LLM generates a dashboard, you want it to *react* to user input—filter, sort, calculate—without a server round-trip for every interaction.
205
+
206
+ And while the current reference implementation is in JavaScript, **nothing prevents cDOM and JPRX from being implemented in other languages like Dart or Swift**. The core concepts—reactive pointers, helper functions, and declarative structure—are universal. You could build a Flutter renderer for cDOM just as easily as Google built one for A2UI.
207
+
208
+ ---
209
+
210
+ ## Custom Components: Extending the Vocabulary
211
+
212
+ A powerful feature of A2UI is **capability negotiation**: the agent queries the client's component catalog before generating UI. This ensures compatibility across different renderers.
213
+
214
+ cDOM takes a different approach. There's no formal negotiation protocol, but the ecosystem makes **adding custom components trivial**.
215
+
216
+ Libraries like **Lightview** and **Juris.js** allow you to define custom HTML elements declaratively:
217
+
218
+ ```javascript
219
+ Lightview.define('my-widget', {
220
+ template: `<div><slot></slot> - Custom!</div>`,
221
+ state: { clicks: 0 }
222
+ });
223
+ ```
224
+
225
+ Once defined, these elements are immediately usable in cDOM:
226
+
227
+ ```json
228
+ { "my-widget": { "children": ["Hello"] } }
229
+ ```
230
+
231
+ The philosophy: the **application developer controls the component catalog**, just as in A2UI. The difference is that cDOM skips the negotiation handshake—the LLM uses components it's been trained to expect for that application. If discovery is needed, a JSON manifest of available components can be provided to the LLM as context.
232
+
233
+ This trade-off prioritizes **simplicity and low overhead** for applications where the component set is known in advance—which, in my experience, is most applications.
234
+
235
+ ---
236
+
237
+ ## Why This Matters for the Future of Agentic UI
238
+
239
+ I believe the next wave of applications will be **agent-first**. Not chatbots with UI bolted on, but intelligent systems where conversation and application dissolve into one.
240
+
241
+ A user might ask:
242
+ > "Show me my sales performance for Q4, highlight anything below target, and let me drill down by region."
243
+
244
+ An LLM should respond not with a paragraph, but with a **live dashboard**: a chart that filters, a table that sorts, a summary that recalculates. When the user says "focus on EMEA," the agent streams a UI patch that updates the view in place.
245
+
246
+ cDOM and JPRX are the foundation for this vision:
247
+ * **For Developers**: Write less JavaScript, define relationships, let reactivity handle the rest.
248
+ * **For LLMs**: A safe, structured, computable expression language as easy to generate as natural text.
249
+ * **For Users**: Rich, instantly reactive interfaces without server round-trip latency.
250
+
251
+ ---
252
+
253
+ ## Get Started with Lightview
254
+
255
+ cDOM and JPRX are part of **Lightview**, my lightweight (~5KB) reactive UI library. It's framework-agnostic, browser-native, and designed for both humans and machines.
256
+
257
+ * **Documentation**: [lightview.dev](https://lightview.dev) - Full guides and API reference
258
+ * **GitHub**: [github.com/anywhichway/lightview](https://github.com/anywhichway/lightview)
259
+ * **npm packages**:
260
+ * Lightview (includes cDOM): [`npm install lightview`](https://www.npmjs.com/package/lightview)
261
+ * JPRX (standalone parser): [`npm install jprx`](https://www.npmjs.com/package/jprx)
262
+
263
+ cDOM is currently in **experimental preview**. I'm actively refining the expression language and helper library based on real-world use cases. I'd love your feedback.
264
+
265
+ ---
266
+
267
+ ## Conclusion: The Spreadsheet Moment for UI
268
+
269
+ Spreadsheets democratized computation. You didn't need to be a programmer to define that `C3 = A1 + B2` and have it update forever.
270
+
271
+ cDOM is designed to be that moment for user interfaces. A format where an LLM—or a human—can declare: *this text shows the count; this button increments it; this chart sums the sales*. And the system handles the rest.
272
+
273
+ In a world where AI agents are becoming the new developers, the language they speak to the browser matters. I think that language should be safe, reactive, and computational from the ground up.
274
+
275
+ **That's cDOM. Welcome to the Computational DOM.**
276
+
277
+ ---
278
+
279
+ *Simon Y. Blackwell is the creator of Lightview, a lightweight reactive library for building web applications. He believes that the best code is the code you don't have to write, and that LLMs should be first-class citizens in the UI development process.*
package/docs/about.html CHANGED
@@ -38,15 +38,15 @@
38
38
  something that felt more like regular HTML than even HTMX does.
39
39
  This would also require thorough and fully interactive documentation accessible via direct URLs and an SPA
40
40
  like experience.
41
- This manadated a router with at least partial "automatic" SSR—where code could execute and replace itself on
41
+ This mandated a router with at least partial "automatic" SSR—where code could execute and replace itself on
42
42
  the server with a simple
43
- DOM emulation and "have-your-cake-and-eat-it-too" single page apps that are SEO enabled without any extra
43
+ DOM emulation and "have-your-cake-and-eat-it-too" single page apps that are SEO-enabled without any extra
44
44
  work.
45
45
  </p>
46
46
 
47
47
  <p>
48
- In today's age, the ability of an LLM to generate cohensive applications using the library is also important
49
- to me. If figured that if an LLM generated it and it followed conventional patterns, it will be able to use
48
+ In today's age, the ability of an LLM to generate cohesive applications using the library is also important
49
+ to me. I figured that if an LLM generated it and it followed conventional patterns, it will be able to use
50
50
  it well and perhaps generate a little less slop.
51
51
  </p>
52
52
 
@@ -55,8 +55,8 @@
55
55
  combo of HTMX, Bau, and
56
56
  Juris with no special attribute names plus HTML template literals, and an SPA router. And, give me a UI
57
57
  component library like
58
- Bau's with automatic custom elment creation but don't build it from scratch. Finally, make it possible to
59
- create SEO enabled apps with no extra work" I also provied a few examples of the kind of code I wanted to
58
+ Bau's with automatic custom element creation but don't build it from scratch. Finally, make it possible to
59
+ create SEO-enabled apps with no extra work." I also provided a few examples of the kind of code I wanted to
60
60
  write
61
61
  using the library.
62
62
  </p>
@@ -64,16 +64,19 @@
64
64
  <p>
65
65
  Naturally, it took a little iterating, but the basic framework was in place after just a few hours of
66
66
  working with both Claude Opus 4.5 and Gemini 3 Pro. I then asked for
67
- an extensive interactive website for documenting and promoting Lightview that also used Lightview, despsite
67
+ an extensive interactive website for documenting and promoting Lightview that also used Lightview, despite
68
68
  the fact that in the age of LLM code generation the need for extensive documentation websites is limited.
69
69
  This took a lot more work, 3
70
- weeks in fact. Very little of this time was spent addressing issues with or enhancing Ligntview. Most of it
71
- was spent adding, debugginng and testing all the UI components. The LLM would get locked in on a particular
72
- approach that worked form simple components bu no more complex ones.
73
- But, that is a story for another time. Here we are 3 weeks later with about 2,000 lines of code for
70
+ weeks in fact. Very little of this time was spent addressing issues with or enhancing Lightview. Most of it
71
+ was spent adding, debugging, and testing all the UI components. The LLM would get locked in on a particular
72
+ approach that worked for simple components but not more complex ones.
73
+ But, that is a story for another time. So, 3 weeks later I had about 2,000 lines of code for
74
74
  Lightview
75
75
  as a whole across three
76
- files, 25,000 lines of component code, and 30,000 lines of documentation.
76
+ files, 25,000 lines of component code, and 30,000 lines of documentation. Lightview has grown a lot since
77
+ then! You can see my article about initial development after week 4 on <a
78
+ href="https://hackernoon.com/lightview-a-lightweight-javascript-framework-for-building-single-page-applications-1768144869105"
79
+ target="_blank">Hackernoon</a>.
77
80
  </p>
78
81
 
79
82
  <p>
@@ -2,7 +2,7 @@
2
2
  <script src="/lightview-router.js?base=/index.html"></script>
3
3
 
4
4
  <div class="docs-layout">
5
- <aside class="docs-sidebar" src="./nav.html"></aside>
5
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
6
6
 
7
7
  <main class="docs-content">
8
8
  <h1>Computed</h1>
@@ -1,7 +1,7 @@
1
1
  <!-- SEO-friendly SPA Shim -->
2
2
  <script src="/lightview-router.js?base=/index.html"></script>
3
3
  <div class="docs-layout">
4
- <aside class="docs-sidebar" src="./nav.html"></aside>
4
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
5
5
  <main class="docs-content">
6
6
  <h1>Effects</h1>
7
7
  <p>
@@ -4,7 +4,7 @@
4
4
  <link rel="stylesheet" href="../components/index.css">
5
5
 
6
6
  <div class="docs-layout">
7
- <aside class="docs-sidebar" src="./nav.html"></aside>
7
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
8
8
 
9
9
  <main class="docs-content">
10
10
  <h1>Elements</h1>
@@ -119,9 +119,58 @@ $('#example').content(app);</code></pre>
119
119
 
120
120
  <h2 id="object-dom">Object DOM (oDOM)</h2>
121
121
  <p>
122
- A more compact JSON representation provided by <strong>Lightview X</strong>. It uses the tag name as a key
123
- to reduce verbosity.
122
+ A more compact JSON representation provided by <strong>Lightview X</strong>. In oDOM, an object with a
123
+ <strong>single key</strong> and an <strong>object value</strong> represents an element. The key is the
124
+ <strong>tag name</strong> (e.g., <code>"div"</code>, <code>"span"</code>) or a <strong>custom element
125
+ function name</strong>. The value object contains the element's attributes.
124
126
  </p>
127
+
128
+ <h3>Reserved Keys</h3>
129
+ <p>
130
+ Certain keys on the value object are reserved and have special meaning instead of being treated as
131
+ attributes:
132
+ </p>
133
+ <table class="api-table">
134
+ <thead>
135
+ <tr>
136
+ <th>Key</th>
137
+ <th>Purpose</th>
138
+ </tr>
139
+ </thead>
140
+ <tbody>
141
+ <tr>
142
+ <td><code>children</code></td>
143
+ <td>An array of child elements, strings, or reactive functions.</td>
144
+ </tr>
145
+ <tr>
146
+ <td><code>attributes</code></td>
147
+ <td>An explicit attributes object (not needed in oDOM since non-reserved keys are attributes). If
148
+ you use this attribute, Lighview MAY assume you are trying to use vDOM not oDOM. Avoid its use
149
+ except for vDOM.
150
+ </td>
151
+ </tr>
152
+ <tr>
153
+ <td><code>tag</code></td>
154
+ <td>Explicitly sets the tag name. If you use this attribute, Lighview MAY assume you are trying to
155
+ use vDOM not oDOM. Avoid its use except for vDOM.</td>
156
+ </tr>
157
+ </tbody>
158
+ </table>
159
+ <p>
160
+ All other keys on the value object are treated as <strong>attribute names</strong>. Keys starting with
161
+ <code>on</code> (like <code>onclick</code>, <code>onmouseenter</code>) are bound as event handlers.
162
+ </p>
163
+
164
+ <h3>Array Shorthand</h3>
165
+ <p>
166
+ If a tag key has an <strong>array</strong> as its value instead of an object, it is shorthand for
167
+ <code>{ &lt;key&gt;: { children: &lt;array&gt; } }</code>:
168
+ </p>
169
+ <pre><code>// These are equivalent:
170
+ { ul: [{ li: ['Item 1'] }, { li: ['Item 2'] }] }
171
+ { ul: { children: [{ li: { children: ['Item 1'] } }, { li: { children: ['Item 2'] } }] } }</code></pre>
172
+
173
+ <h3>Example</h3>
125
174
  <div id="syntax-object">
126
175
  <pre><script>
127
176
  examplify(document.currentScript.nextElementSibling, {
@@ -134,7 +183,7 @@ $('#example').content(app);</code></pre>
134
183
  </script><code contenteditable="true">const { signal, tags, $ } = Lightview;
135
184
  const count = signal(0);
136
185
  const app = { div: { class: 'container', children: [
137
- { h1: { children: ['Hello Lightview'] } },
186
+ { h1: ['Hello Lightview'] },
138
187
  { p: { children: [() => `Count: ${count.value}`] } },
139
188
  { button: { onclick: () => count.value++, children: ['Click me'] } }
140
189
  ]}};
@@ -197,27 +246,9 @@ const greeting = div(
197
246
  );
198
247
  // Initial result: <div>Hello, John Doe !</div></code></pre>
199
248
 
200
- <h2 id="attributes-events">Attributes & Events</h2>
201
- <p>
202
- Pass attributes as the first argument (Tagged API) or in the attributes object (others):
203
- </p>
204
- <pre><code>// Standard attributes
205
- div({
206
- id: 'my-div',
207
- class: 'container active',
208
- style: 'color: red;',
209
- 'data-value': '42'
210
- })
211
-
212
- // Reactive attributes - use functions!
213
- div({
214
- class: () => isActive.value ? 'active' : 'inactive',
215
- style: () => `opacity: ${visible.value ? 1 : 0}`,
216
- disabled: () => isLoading.value
217
- })
218
-
219
- // Event handlers - use "on" prefix
220
- button({
249
+ <h2 id="attributes-events">Events</h2>
250
+ <p>Use standard event handlers prefixed with "on".</p>
251
+ <pre><code>button({
221
252
  onclick: (e) => handleClick(e),
222
253
  onmouseenter: () => setHovered(true),
223
254
  onmouseleave: () => setHovered(false)
@@ -4,7 +4,7 @@
4
4
  <link rel="stylesheet" href="../components/index.css">
5
5
 
6
6
  <div class="docs-layout">
7
- <aside class="docs-sidebar" src="./nav.html"></aside>
7
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
8
8
 
9
9
  <main class="docs-content">
10
10
  <h1>Enhance</h1>
@@ -2,7 +2,7 @@
2
2
  <script src="/lightview-router.js?base=/index.html"></script>
3
3
 
4
4
  <div class="docs-layout">
5
- <aside class="docs-sidebar" src="./nav.html"></aside>
5
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
6
6
 
7
7
  <main class="docs-content">
8
8
  <h1>Hypermedia</h1>
@@ -4,7 +4,7 @@
4
4
  </script>
5
5
 
6
6
  <div class="docs-layout">
7
- <aside class="docs-sidebar" src="./nav.html"></aside>
7
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
8
8
 
9
9
  <main class="docs-content">
10
10
  <h1>API Reference</h1>
package/docs/api/nav.html CHANGED
@@ -1,4 +1,4 @@
1
- <nav class="docs-nav">
1
+ <nav data-preserve-scroll="docs-nav" class="docs-nav">
2
2
  <div class="docs-nav-section">
3
3
  <div class="docs-nav-title">Elements</div>
4
4
  <a href="./elements.html" class="docs-nav-link">Comparison</a>
@@ -13,7 +13,7 @@
13
13
  <a href="./elements.html#text" class="docs-nav-link" style="font-size: 0.85em;">text</a>
14
14
  </div>
15
15
  </div>
16
- <a href="./elements.html#attributes-events" class="docs-nav-link">Attributes & Events</a>
16
+ <a href="./elements.html#attributes-events" class="docs-nav-link">Events</a>
17
17
  <a href="./elements.html#children" class="docs-nav-link">Children</a>
18
18
  <a href="./elements.html#dom-el" class="docs-nav-link">The domEl Property</a>
19
19
  </div>
@@ -28,7 +28,32 @@
28
28
  </div>
29
29
  <div class="docs-nav-section">
30
30
  <div class="docs-nav-title">Lightview X</div>
31
- <a href="./state.html" class="docs-nav-link">State (Deep Reactivity)</a>
31
+ <div class="docs-nav-item">
32
+ <a href="./state.html" class="docs-nav-link">State (Deep Reactivity)</a>
33
+ <div class="docs-nav-subsection" style="margin-left: 1rem; border-left: 1px solid var(--site-border);">
34
+ <a href="./state.html#shortcomings" class="docs-nav-link" style="font-size: 0.85em;">Shortcomings of
35
+ Signals</a>
36
+ <a href="./state.html#state-to-the-rescue" class="docs-nav-link" style="font-size: 0.85em;">State to the
37
+ Rescue</a>
38
+ <a href="./state.html#state-function" class="docs-nav-link" style="font-size: 0.85em;">State
39
+ Function</a>
40
+ <a href="./state.html#nested-objects" class="docs-nav-link" style="font-size: 0.85em;">Nested
41
+ Objects</a>
42
+ <a href="./state.html#in-the-ui" class="docs-nav-link" style="font-size: 0.85em;">In the UI</a>
43
+ <a href="./state.html#array-methods" class="docs-nav-link" style="font-size: 0.85em;">Array Methods</a>
44
+ <a href="./state.html#date-methods" class="docs-nav-link" style="font-size: 0.85em;">Date Methods</a>
45
+ <a href="./state.html#named-state" class="docs-nav-link" style="font-size: 0.85em;">Named State</a>
46
+ <a href="./state.html#stored-state" class="docs-nav-link" style="font-size: 0.85em;">Stored State</a>
47
+ <a href="./state.html#schema-validation" class="docs-nav-link" style="font-size: 0.85em;">Schema
48
+ Validation</a>
49
+ <a href="./state.html#json-schema-lite" class="docs-nav-link" style="font-size: 0.85em;">JSON Schema
50
+ Lite</a>
51
+ <a href="./state.html#transformations" class="docs-nav-link"
52
+ style="font-size: 0.85em;">Transformations</a>
53
+ <a href="./state.html#lite-vs-full" class="docs-nav-link" style="font-size: 0.85em;">Lite vs. Full
54
+ Validators</a>
55
+ </div>
56
+ </div>
32
57
  <div class="docs-nav-item">
33
58
  <a href="./hypermedia.html" class="docs-nav-link">Hypermedia</a>
34
59
  <div class="docs-nav-subsection" style="margin-left: 1rem; border-left: 1px solid var(--site-border);">
@@ -2,7 +2,7 @@
2
2
  <script src="/lightview-router.js?base=/index.html"></script>
3
3
 
4
4
  <div class="docs-layout">
5
- <aside class="docs-sidebar" src="./nav.html"></aside>
5
+ <aside class="docs-sidebar" src="./nav.html" data-preserve-scroll="docs-nav"></aside>
6
6
 
7
7
  <main class="docs-content">
8
8
  <h1>Signals</h1>